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
, которая имеет размер целого, который вы можете поместить в макрос.