Внедрение оператора sizeof
Я попытался реализовать оператор sizeof. Я сделал это таким образом.
#define my_sizeof(x) ((&x + 1) - &x)
Но он всегда заканчивался тем, что давал результат как "1" для любого типа данных.
У меня тогда был googled для этого.. и я нашел код typecasted
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
И код работает, если это придумано.. Я не понимаю, почему.. Этот код также PADDING STRUCTURE отлично.
Он также работает для
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
Может кто-нибудь объяснить, как это работает, если typecasted и если не typecasted?
Спасибо заранее.
Ответы
Ответ 1
Результат вычитания указателя находится в элементах, а не в байтах. Таким образом, первое выражение оценивает 1
по определению.
В стороне, вы действительно должны использовать круглые скобки в макросах:
#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
В противном случае попытка использования my_sizeof()
в выражении может привести к ошибкам.
Ответ 2
Оператор sizeof
является частью спецификации языка C (и С++) и реализуется внутри компилятора (front-end). Невозможно реализовать его с другими конструкциями C (если вы не используете расширения GCC, такие как typeof), поскольку он может принимать любые типы или выражения как операнд, без какого-либо побочного эффекта (например, sizeof((i>1)?i:(1/i))
не будет разбиваться, когда i==0
, но ваш макрос my_sizeof
будет разбиваться с делением на ноль). См. Также C правила кодирования, и wikipedia.
Вы должны понимать C арифметику указателя. См. этот вопрос. Разница указателей выражается в элементах, а не байтах.
Ответ 3
Но это всегда приводило к тому, что результат был равен "1" для любого типа данных
Да, это то, как работает арифметика указателя. Он работает в единицах указанного типа. Таким образом, при нажатии char *
выполняются единицы char
, которые вы хотите.
Ответ 4
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
Этот макрос my_sizeof()
не будет работать в следующих случаях:
-
sizeof 1
- 4 байта (для платформы с 4 байтами int
)
my_sizeof(1)
- не будет компилироваться вообще.
-
sizeof (int)
- 4 байта (для платформы с 4 байтами int
)
my_sizeof(int)
- не будет компилировать код вообще.
Он будет работать только для переменных. Он не будет работать для таких типов данных, как int
, float
, char
и т.д., Для таких литералов, как 2
, 3.4
, 'A'
и т.д., А также для выражений rvalue, таких как a+b
или foo()
.
Ответ 5
#define my_sizeof(x) ((&x + 1) - &x)
&x
дает адрес переменной (пусть говорят double x), объявленной в программе, и увеличивая ее с помощью 1, дает адрес, в котором можно сохранить следующую переменную типа x (здесь addr_of(x) + 8
, для размера двойника - 8Byte).
Разница дает результат, что количество переменных типа x
может быть сохранено в том объеме памяти, который, очевидно, будет равен 1 для типа x (для увеличения его с 1 и с учетом того, что мы имеем сделанный).
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
приведя его в char*
и получив разницу, скажет нам, сколько переменных типа char
может быть сохранено в данном пространстве памяти (разница). Поскольку каждый char
требует только 1 байт памяти, поэтому (объем памяти)/1 будет указывать количество байтов между двумя последовательными ячейками памяти типа переменной, переданной макросу, и, следовательно, объем памяти, в котором переменная тип x
требует.
Но вы не сможете передать какой-либо литерал этому макросу и узнать их размер.
Ответ 6
# define my_sizeof (x) ((& x + 1) - & x)
& x дает адрес вашей переменной и увеличивает его на один (& x + 1), укажет адрес, где может быть сохранена другая переменная типа x.
Теперь, если мы сделаем арифметику по этим адресам, например ((& x + 1) - & x), то он скажет, что внутри ((& x + 1) - & x) диапазон адреса 1 переменная типа x может сохраняться.
Теперь, если мы будем указывать этот объем памяти с (char *) [поскольку размер char равен 1 байту, а приращение char * будет перемещаться только с одним байтом), мы получим номер байтов типа x потребляет