This program gives output as 5. But after replacing all macros, it would result in --5
. This should cause an compilation error, trying to decrement the 5
. But it compiles and runs fine.
#include <stdio.h>
#define A -B
#define B -C
#define C 5
int main()
{
printf("The value of A is %d\n", A);
return 0;
}
Why is there no error?
Here are the steps for the compilation of the statement
printf("The value of A is %d\n", A);
:printf
,(
,"The value of A is %dn"
,,
,A
,)
and;
.A
is a macro that expands to the 2 tokens-
andB
.B
is also a macro and gets expanded to-
andC
.C
is again a macro and gets expanded to5
.0a
). In this example, the tokens are identical.printf
,(
,"The value of A is %d\n"
,,
,-
,-
,5
,)
,;
matches a function call toprintf
with 2 arguments: a format string and a constant expression-
-
5
, which evaluates to5
at compile time.the code is therefore equivalent to
printf("The value of A is %d\n", 5);
. It will produce the output:This sequence of macros is expanded as tokens, not strictly a sequence of characters, hence
A
does not expand as--5
, but rather as- -5
. Good C compilers would insert an extra space when preprocessing the source to textual output to ensure the resulting text produces the same sequence of tokens when reparsed. Note however that the C Standard does not say anything about preprocessing to textual output, it only specifies preprocessing as one of the parsing phases and it is a quality of implementation issue for compilers to not introduce potential side effects when preprocessing to textual output.There is a separate feature for combining tokens into new tokens in the preprocessor called token pasting. It requires a specific operator
##
and is quite tricky to use.Note also that macros should be defined with parentheses around each argument and parentheses around the whole expansion to prevent operator precedence issues:
Whenever we use #include in C program, compiler will replace the variable with its value wherever it is used.
So when we print A , it will execute in following steps.
A=>-B
B=>-C
A=>-(-C)=>C
So when we print value of A, it comes out to be 5.
Generally these #define statements are used to declare value of constants that are to be used through out the code.
For more info see this link on #define directive
Two consecutive dashes are not combined into a single pre-decrement operator
--
because C preprocessor works with individual tokens, effectively inserting whitespace around macro substitutions. Running this program throughgcc -E
produces the following output:
Note the space after the first
-
.According to the standard, macro replacements are performed at the level of preprocessor tokens, not at the level of individual characters (6.10.3.9):
Therefore, the two dashes
-
constitute two different tokens, so they are kept separate from each other in the output of the preprocessor.