sizeof() is not executed by preprocessor

2019-06-15 00:40发布

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

9条回答
我命由我不由天
2楼-- · 2019-06-15 01:13

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]).

查看更多
来,给爷笑一个
3楼-- · 2019-06-15 01:16

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楼-- · 2019-06-15 01:19

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])
查看更多
Lonely孤独者°
5楼-- · 2019-06-15 01:21

#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.

查看更多
三岁会撩人
6楼-- · 2019-06-15 01:29

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

查看更多
Juvenile、少年°
7楼-- · 2019-06-15 01:30

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.

查看更多
登录 后发表回答