Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding macros in C [duplicate]

Why is the output from the following code the value 5?

#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;
}
like image 969
Anwar Hussain Avatar asked Jul 05 '17 19:07

Anwar Hussain


2 Answers

This is a tricky question because it is a stress test for the compiler preprocessor.

Depending if the preprocessor is an integrated phase of the compiler or a separate program passing its output to the compiler via a file or a pipe and in this case whether it is careful enough to not perform erroneous token pasting, you may get the expected output: 5 or you may get a compilation error.

After the preprocessed contents of stdio.h, the source code expands to:

int main()
{
  printf("The value of A is %d\n", --5);
  return 0;
}

But the two - are separate tokens, so depending if the preprocessor separates them in its output or not, you may get a program that outputs 5 or one that does not compile because -- cannot be applied to a literal 5.

Both the gcc and the clang preprocessors behave correctly and separate the - with an extra space to prevent token pasting when they produce the preprocessor output with the -E command line option. They output this as preprocessed source code after the expansion of <stdio.h>:

int main()
{
  printf("The value of A is %d\n", - -5);
  return 0;
}

Try your own compiler to check how it expands the source code. It seems Visual Studio 2013 and 2015 fail the test and reject the program with an error.

To makes things clear, I do not say the behavior of the program should depend on the compiler architecture. I was hoping at least one common C compiler would mishandle this conformance test. I am not surprised MS Visual Studio 2013 and 2015 fail this test.

The extra space in only needed in the textual output of the preprocessor. It does not matter if Visual Studio uses multiple separate phases or not, the source program is perfectly valid and their failure to compile it is a BUG.

like image 64
chqrlie Avatar answered Sep 18 '22 21:09

chqrlie


No need to compile this code, just use gcc -E on it (preprocessor) and see what happens:

<lots of output expanding stdio.h> ...

int main()
{
  printf("The value of A is %d\n", - -5);
  return 0;
}

Obviously the result is 5 (which could have been guessed by looking at the nested macros, but a small preprocessor test doesn't hurt).

(Other answers noted that some compilers may handle the preprocessing of the minus signs which would result in a compiler error. gcc handles that nicely.)

like image 42
Jean-François Fabre Avatar answered Sep 20 '22 21:09

Jean-François Fabre