Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there logical short-circuiting in the C preprocessor?

Tags:

c++

c

gcc

The gcc docs for cpp explain about the #if directive:

[...] and logical operations (&& and ||). The latter two obey the usual short-circuiting rules of standard C.

What does that mean? There is no evaluation of expressions during preprocessing, so how can it be short-circuited?

like image 991
not-a-user Avatar asked Jun 04 '14 12:06

not-a-user


People also ask

Do logical operators use short-circuit in C?

Like C, Perl provides the && (logical AND) and || (logical OR) operators. They evaluate from left to right (with && having slightly higher precedence than || ) testing the truth of the statement.

Does C have short-circuit evaluation?

In imperative language terms (notably C and C++), where side effects are important, short-circuit operators introduce a sequence point – they completely evaluate the first argument, including any side effects, before (optionally) processing the second argument.

What is the short-circuiting in C expressions?

Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression. The compiler stops evaluating the further sub-expressions as soon as the value of the expression is determined.

What does the C preprocessor do?

The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation. It is called a macro processor because it allows you to define macros, which are brief abbreviations for longer constructs.


2 Answers

Very simple: undefined macros have numeric value zero, and division by zero is illegal.

#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42 #define USE_CELLPOOL #endif 

#if does evaluate the rest of its line as an integer constant expression. Your linked documentation begins:

The ‘#if’ directive allows you to test the value of an arithmetic expression, rather than the mere existence of one macro.

That isn't a gcc extension, the Standard's syntax for #if is

#ifconstant-expression new-line groupopt.

The C99 preprocessor treats all constants as [u]intmax_t.

like image 180
jthill Avatar answered Sep 21 '22 17:09

jthill


What they are referring to is && and || operators for #if

#if defined (AAA) || defined (BBB) 

If defined (AAA) is defined then defined (BBB) is never evaluated.


UPDATE

So running the calculation will be short circuited. For example, if you build with -Wundef to warn about the usage of undefined macros.

#if defined FOO && FOO > 1000 #endif  #if FOO > 1000 #endif 

will result in

thomas:~ jeffery$ gcc foo.c -Wundef foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef] #if FOO > 1000     ^ 1 warning generated. 

So the first version does not generate the undefined macro warning, because FOO > 1000 is not evaluated.


OLD MUSINGS

This become important if the second part is a macro which has side effects. The macro would not be evaluated, so the side effects would not take place.


To avoid macro abuse I'll give a somewhat sane example

#define FOO #define IF_WARN(x) _Pragma (#x) 1 #if defined(FOO) || IF_WARN(GCC warning "FOO not defined") #endif 

Now that I constructed this example, I now run into a problem. IF_WARN is always evaluated.

huh, more research needed.


Well foo… now that I read it again.

Macros. All macros in the expression are expanded before actual computation of the expression's value begins.

like image 30
Jeffery Thomas Avatar answered Sep 20 '22 17:09

Jeffery Thomas