Sizeof() не выполняется препроцессором

#if sizeof(int) != 4
/* do something */

Использование sizeof внутри #if не работает, а внутри #define работает, почему?

#define size(x) sizeof(x)/sizeof(x[0]) /*works*/

Ответы

Ответ 1

Ничто не является злом - все может быть неправильно использовано или в вашем случае неправильно понято. Оператор sizeof является компилятором, но функции компилятора недоступны для препроцессора (который выполняется до того, как компилятор задействован), и поэтому не могут использоваться в директивах препроцессора #if.

Однако, когда вы говорите:

#define size(x) sizeof(x)/sizeof(x[0])

и используйте его:

size(a)

препроцессор выполняет текстовую подстановку, переданную компилятору:

sizeof(a)/sizeof(a[0])

Ответ 2

Препроцессор не может оценить результаты оператора sizeof. Это вычисляется компилятором, после завершения препроцессора.

Так как второе выражение приводит к вычислению времени компиляции, оно работает. Первый - это невозможный тест для препроцессора.

Ответ 3

C "Препроцессор" Макросы только оценивают константы и другие макросы

Короткий ответ представляет собой выражение препроцессора, которое обеспечивает значимую оценку выражения, состоящего из других макросов и констант препроцессора.

Попробуйте это, вы не получите сообщение об ошибке:

#if sizeof < 2
int f(int x) { return x; }
#endif

Если вы создаете сборку, вы обнаружите, что sizeof < 2 компилирует функцию, а sizeof >= 2 - нет. Не возвращает ошибку.

Что происходит? Оказывается, что, за исключением самих макросов препроцессора, все идентификаторы в выражении препроцессора ( "макро" ) заменяются на 0. Таким образом, выше #if совпадает с:

#if Easter_Bunny < 2

или

#if 0 < 2

Вот почему вы фактически не получаете какую-либо ошибку при ошибочном использовании оператора sizeof в выражении препроцессора.

Как это бывает, sizeof является оператором, но он также является идентификатором, а идентификаторы, которые сами по себе не являются макросами, превращаются в 0 в выражениях препроцессора. Препроцессор работает, по крайней мере, концептуально, перед компилятором. Он может превратить синтаксис не C в C, поэтому в момент его запуска программа C еще не была проанализирована. Пока нельзя ссылаться на реальные объекты C: их не существует.

И естественно, sizeof в заменяющем тексте определения просто передается компилятору, как, ну, заменяющий текст, в котором используется макрос.

Ответ 4

#define - это просто замена текста. #if - условная препроцессорная директива оценивает sizeof(), но во время предварительной обработки препроцессор понятия не имеет, что такое sizeof(). Препроцессор работает до этапа лексического анализа.

Ответ 5

sizeof заменяется во время компиляции. Перед запуском компиляции выполняется предварительная обработка.

Ответ 6

Компилятор не касается ни одной строки. Скорее, препроцессор копирует файл, заменяя любые экземпляры размера (x) на ваш макрос. Компилятор видит эти замены.

Ответ 7

Препроцессор не знает оператора sizeof, он просто не может его понять. Таким образом, #if не работает, поскольку он должен понимать, что он работает, потому что это условный условный препроцессор; он должен знать, оценивает ли он значение true или false.

Но #define не нужно понимать sizeof, так как #define предназначен только для замены текста. Препроцессор ищет макрос size (определенный в #define) в исходном коде и заменяет его тем, что он определен, который находится в вашем случае sizeof(x)/sizeof(x[0]).

Ответ 8

Причина, по которой он не работает, заключается в том, что макросы предварительного процессора "оцениваются" в проходе до того, как код достигнет компилятора. Поэтому в директиве if-pre-size sizeof (int) (на самом деле sizeof (int)!= 4) нельзя оценить, потому что это выполняется компилятором, а не препроцессором.

Однако оператор определения просто выполняет подстановку текста, и поэтому, когда дело доходит до компилятора, везде, где у вас есть "размер (x)", у вас будет "sizeof (x)/sizeof (x [0])" вместо, а затем это оценивается там на этапе компиляции... в каждой точке кода, где у вас был "размер (x)"

Ответ 9

Если вы хотите проверить размер целого числа в процессоре, используйте свою систему make, чтобы узнать размер целого числа в вашей системе перед запуском препроцессора и записать его в файл заголовка, например. #define SIZEOF_INT 4, включите этот заголовочный файл и сделайте #if SIZEOF_INT == 4

Например, если вы используете cmake, вы можете использовать переменную CMAKE_SIZEOF_INT, которая имеет размер целого, который вы можете поместить в макрос.