я видел эту сложную декларацию SizeOf оператора где-то в книге, которая дразнила меня:комплексов Декларации оператора SizeOf в С
#define SIZEOF(int) (int)&((int *)0)[1]
Может ли один объяснить это заявление, что происходит здесь ...?
я видел эту сложную декларацию SizeOf оператора где-то в книге, которая дразнила меня:комплексов Декларации оператора SizeOf в С
#define SIZEOF(int) (int)&((int *)0)[1]
Может ли один объяснить это заявление, что происходит здесь ...?
Здесь с [1]
части «расширена»:
(int)(&(*(((int*)0) + 1)))
Теперь вы видите, как это работает?
0 увеличится на sizeof
int
из-за свойства арифметиков указателей и окончательного int
броска получает вам значение результирующего адреса, который является «размером».
Это совершенно неопределенное поведение, хотя (арифметика на null и, возможно, разыменование недействительного указателя), довольно бессмысленно.
Обновление с параметром макроса не имеет большого смысла. Окончательный отбор должен, вероятно, быть std::uintptr_t
.
+1 для указания неопределенного поведения. –
Обратите внимание, что 'int' - это параметр макроса –
-1: Преобразование' [] 'в' * (x + y) 'не является частью« расширения », запутанное здесь, поскольку оно связано с макросами, вам нужно предоставить аргументы развернуть макрос, и бесполезно говорить «UB» без объяснения причин. В этом случае единственным источником неквалифицированного UB является интегральное переполнение, что не имеет значения. – Potatoswatter
Во-первых - это путают вещи с термином int
- мы, естественно, считаем, что это ключевое слово знакомого типа, однако в данном случае это не так - вместо этого это аргумент макроса. Поэтому для упрощения рассмотрят макрос следующим образом:
#define SIZEOF(type) &((type *)0)[1]
Теперь, глядя на него таким образом, это, возможно, легче увидеть, что макрос первого адрес отливки 0 быть указателем на type
, а затем он принимает адрес второго элемента. Это покажет размер.
Приятно, что вы заметили запутанное имя аргумента! –
+1 для указания запутанного использования 'int' в качестве параметра макроса - другие ответы, опубликованные до сих пор, не обнаружили этого –
Он определяет SIZEOF
как размер целого числа.
(int *)0
является указателем INT по адресу нулевого[1]
получает доступ к следующей целого числа после того.(int *)0
имеет нулевой адрес, после того, как он имеет адрес sizeof int
, поскольку он поступает сразу после предыдущего.(int)
отдает его числу, так как размер является числом, а не указателем.Очевидно, что это неприятный взлом, нужно просто использовать sizeof int
.
. Обратите внимание, что' int' является макропараметром –
Только после того, как OP отредактировал свой вопрос , – ThiefMaster
@ThiefMaster предварительная запись была '#define SIZEOF (int) & ((int *) 0) [1]'. Я считаю, что в этом случае «int» все еще является макропараметром, но интервал между линиями делает его менее очевидным. Правильно ли, или есть какое-то специальное правило относительно интервала в макроопределениях? – mah
Пожалуйста, укажите имя/автора книги, чтобы другие могли избежать этого. –
напоминает мне о том, что я нашел в этой книге: http://www.amazon.com/The-Puzzle-Book-Alan-Feuer/dp/0201604612/ref=la_B001IXRU2O_1_1?ie=UTF8&qid=1338723178&sr=1-1 – Levon
Зачем отмечен как C++? – iammilind