Внедрение оператора 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 потребляет