Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this macro replaced as 20 instead 10?

1. #define NUM 10 2. #define FOO NUM 3. #undef NUM 4. #define NUM 20 5.  6. FOO 

When I only run the preprocessor, the output file contains 20.

However, from what I understand, the preprocessor simply does text replacement. So this is what I think is happening (which is obviously wrong but idky):

  1. NUM is defined as 10.
  2. Therefore, in line 2, NUM is replaced as 10. So now we have "#define FOO 10".
  3. NUM is undefined.
  4. NUM is redefined and now is 20.
  5. FOO is replaced according to line 2, which was before line 4's redefinition, and is 10.

So I think the output should be 10 instead of 20. Can anything explain where it went wrong?

like image 256
OneZero Avatar asked Aug 21 '15 18:08

OneZero


People also ask

Can we change the value of macro?

You can't. Macros are expanded by the Preprocessor, which happens even before the code is compiled. It is a purely textual replacement.

What is macro replacement in C?

Macro substitution is a mechanism that provides a string substitution. It can be achieved through "#deifne". It is used to replace the first part with the second part of the macro definition, before the execution of the program. The first object may be a function type or an object.

What is the size of macro in C?

In your case 8 bytes.


2 Answers

The text replacement is done where the macro is used, not where you wrote the #define. At the point you use FOO, it replaces FOO with NUM and NUM is currently defined to be 20.

like image 148
David Avatar answered Oct 11 '22 21:10

David


In the interests of collecting all the relevant specifications from the standards, I extracted this information from a comment thread, and added C++ section numbers, based on draft N4527 (the normative text is identical in the two standards). The standard(s) are absolutely clear on the subject.

  1. #define preprocessor directives do not undergo macro replacement.

    (C11 §6.10¶7; C++ §16[cpp] ¶6): The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.

  2. After a macro is replaced with its replacement text, the new text is rescanned. Preprocessor tokens in the replacement are expanded as macros if there is an active macro definition for the token at that point in the program.

    (C11 §6.10.3¶9; C++ §16.3[cpp.replace] ¶9) A preprocessing directive of the form

    # define identifier replacement-list new-line

    defines an object-like macro that causes each subsequent instance of the macro name to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.

  3. A macro definition is active from the line following the #define until an #undef for the macro name, or the end of the file.

    (C11 §6.10.3.5¶1; C++ §16.3.5[cpp.scope] ¶1) A macro definition lasts (independent of block structure) until a corresponding #undef directive is encountered or (if none is encountered) until the end of the preprocessing translation unit. Macro definitions have no significance after translation phase 4.

If we look at the program:

#define NUM 10 #define FOO NUM #undef NUM #define NUM 20 FOO  

we see that the macro definition of NUM in line 1 lasts exactly to line 3. There is no replaceable text in those lines, so the definition is never used; consequently, the program is effectively the same as:

#define FOO NUM #define NUM 20 FOO  

In this program, at the third line, there is an active definition for FOO, with replacement list NUM, and for NUM, with replacement list 20. The FOO is replaced with its replacement list, making it NUM, and then that is once again scanned for macros, resulting in NUM being replaced with its replacement list 20. That replacement is again rescanned, but there are no defined macros, so the end result is that the token 20 is left for processing in translation phase 5.

like image 22
rici Avatar answered Oct 11 '22 22:10

rici