sizeof() 不由预处理器执行
#if sizeof(int) != 4
/* do something */
在 #if
内使用 sizeof 不起作用,而在 #define
内使用 sizeof 则有效,为什么?
#define size(x) sizeof(x)/sizeof(x[0]) /*works*/
#if sizeof(int) != 4
/* do something */
Using sizeof inside #if
doesn't work while inside #define
it works, why?
#define size(x) sizeof(x)/sizeof(x[0]) /*works*/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
没有什么是邪恶的——一切都可能被滥用,或者在你的情况下被误解。
sizeof
运算符是编译器功能,但编译器功能不可用于预处理器(在编译器介入之前运行),因此不能在#if
预处理器中使用指令。但是,当您说:
并使用它时:
预处理器执行传递给编译器的文本替换:
Nothing is evil - everything can be misused, or in your case misunderstood. The
sizeof
operator is a compiler feature, but compiler features are not available to the preprocessor (which runs before the compiler gets involved), and so cannot be used in#if
preprocessor directives.However, when you say:
and use it:
the preprocessor performs a textual substitution that is handed to the compiler:
C“预处理器”宏仅计算常量和其他宏
简单的答案是预处理器表达式仅对由其他预处理器宏和常量组成的表达式提供有意义的计算。
试试这个,您将不 得到一个错误:
如果你生成程序集,你会发现
sizeof < 2
编译该函数,而sizeof >= 2
则不编译。两者都不返回错误。这是怎么回事?事实证明,除了预处理器宏本身之外,预处理器(“宏”)表达式中的所有标识符都被替换为 0。因此上面的
#if
等同于:or
这就是为什么你在预处理器表达式中错误地使用
sizeof
运算符时,实际上不会出现任何类型的错误。碰巧,
sizeof
是一个运算符,但它也是一个标识符,并且本身不是宏的标识符在预处理器表达式中都会变成0
。至少在概念上,预处理器在编译器之前运行。它可以将非 C 语法转换为 C 语法,因此在运行时,C 程序甚至还没有被解析。目前还不可能引用实际的 C 对象:它们不存在。当然,定义的替换文本中的
sizeof
会简单地传递给编译器,作为使用宏的替换文本。C "Preprocessor" Macros Only Evaluate Constants and Other Macros
The short answer is a preprocessor expression only provides a meaningful evaluation of an expression composed of other preprocessor macros and constants.
Try this, you will not get an error:
If you generate assembly, you will find that
sizeof < 2
compiles the function andsizeof >= 2
does not. Neither returns an error.What's going on? It turns out that, except for preprocessor macros themselves, all identifiers in a preprocessor ("macro") expression are replaced with 0. So the above
#if
is the same as saying:or
This is why you don't actually get any sort of error when mistakenly using the
sizeof
operator in a preprocessor expression.As it happens,
sizeof
is an operator, but it's also an identifier, and identifiers that are not themselves macros all turn into0
in preprocessor expressions. The preprocessor runs, at least conceptually, before the compiler. It can turn non-C syntax into C so at the point it is running, the C program hasn't even been parsed yet. It isn't possible to reference actual C objects yet: they don't exist.And naturally, a
sizeof
in the replacement text of a definition is simply passed through to the compiler as, well, the replacement text where the macro is used.预处理器无法评估
sizeof
运算符的结果。这是在预处理器完成很久之后由编译器计算的。由于第二个表达式导致编译时计算,因此它有效。第一个是对预处理器的不可能测试。
The preprocessor cannot evaluate the results of the
sizeof
operator. That is calculated by the compiler, long after the preprocessor is finished.Since the second expression results in a compile-time computation, it works. The first is an impossible test for the preprocessor.
#define
只是文本替换。#if
是一个条件预处理器指令,它会计算sizeof()
,但在预处理时,预处理器并不知道sizeof()
是什么。预处理器在词法分析阶段之前运行。#define
is merely text replacement.#if
being a conditional preprocessor directive evaluatessizeof()
but at the time of preprocessing the preprocessor has no idea whatsizeof()
is. Preprocessor runs before the lexical analysis phase.sizeof 在编译时被替换。
预处理在编译开始之前运行。
sizeof is replaced at compile time.
Preprocessing runs before compile starts.
编译器不会触及任何一行。相反,预处理器会破坏文件,用宏替换任何 size(x) 实例。编译器确实看到了这些替换。
The compiler doesn't touch either line. Rather, the preprocessor rips through the file, replacing any instances of size(x) with your macro. The compiler DOES see these replacements.
预处理器不知道
sizeof
运算符,它只是无法理解它。所以#if 不起作用,因为它必须理解它才能工作,因为它是一个有条件的条件预处理器;它需要知道它的评估结果是 true 还是 false。但是#define不需要理解sizeof,因为#define只是用于文本替换。预处理器在源代码中搜索
size
宏(在#define
中定义),并将其替换为它定义的内容,即您的情况sizeof( x)/sizeof(x[0])
。Preprocessor doesn't know
sizeof
operator, it just cannot understand it. So#if
doesn't work, since it has to understand it to work, because it is a conditional conditional preprocessor; it needs to know whether it evaluates to true or false.But
#define
doesn't need to understandsizeof
, as#define
is just for text replacement. Preprocessor searchessize
macro (defined in#define
) in the source code, and replaces it with what it is defined to be, which is in your casesizeof(x)/sizeof(x[0])
.它不起作用的原因是因为在代码到达编译器之前预处理器宏是在一次传递中“评估”的。因此,在 if 预处理器指令中,无法计算 sizeof(int) (实际上是 sizeof(int) != 4),因为这是由编译器而不是预处理器完成的。
不过,define 语句只是进行了文本替换,因此当涉及到编译器时,在任何有“size(x)”的地方,都会有“sizeof(x)/sizeof(x[0])”,然后这在编译阶段进行评估...在代码中具有“size(x)”的每个点
The reason it doesn't work is because the pre-processor macros are 'evaluated' in a pass before the code reaches the compiler. So in the if pre-processor directive, the sizeof(int) (actually the sizeof(int) != 4) cannot be evaluated because that is done by the compiler, not the pre-processor.
The define statement though, simply does a text substitution, and so when it comes to the compiler, everywhere you had 'size(x)' you would have 'sizeof(x)/sizeof(x[0])' instead, and then this evaluates there at the compile stage... at every point in the code where you had 'size(x)'
如果您想检查处理器中整数的大小,请在运行预处理器之前使用 make 系统来发现系统上整数的大小,并将其写入头文件,例如
#define SIZEOF_INT 4
,包含此头文件并执行#if SIZEOF_INT == 4
例如,如果您使用 cmake,则可以使用
CMAKE_SIZEOF_INT
变量,该变量的大小为整数你可以放入一个宏。If you want to check the size of the integer in the processor, use your make system to discover the size of integer on your system before running the preprocessor and write it to a header file as e.g.
#define SIZEOF_INT 4
, include this header file and do#if SIZEOF_INT == 4
For example, if you use cmake, you can use the
CMAKE_SIZEOF_INT
variable which has the size of the integer which you can put in a macro.