sizeof() is not executed by preprocessor

一笑奈何 提交于 2019-12-08 15:55:27

问题


#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*/

回答1:


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:

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

and use it:

size(a)

the preprocessor performs a textual substitution that is handed to the compiler:

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



回答2:


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 sizeof < 2
int f(int x) { return x; }
#endif

If you generate assembly, you will find that sizeof < 2 compiles the function and sizeof >= 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:

#if Easter_Bunny < 2

or

#if 0 < 2

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 into 0 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.




回答3:


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.




回答4:


#define is merely text replacement. #if being a conditional preprocessor directive evaluates sizeof() but at the time of preprocessing the preprocessor has no idea what sizeof() is. Preprocessor runs before the lexical analysis phase.




回答5:


sizeof is replaced at compile time. Preprocessing runs before compile starts.




回答6:


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.




回答7:


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 understand sizeof, as #define is just for text replacement. Preprocessor searches size macro (defined in #define) in the source code, and replaces it with what it is defined to be, which is in your case sizeof(x)/sizeof(x[0]).




回答8:


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)'




回答9:


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.



来源:https://stackoverflow.com/questions/6081842/sizeof-is-not-executed-by-preprocessor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!