Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does recursion in the C preprocessor abuse an inconsistency in the standard?

Consider this code:

#define MAP_OUT

#define A(x) B MAP_OUT (x)
#define B(x) A MAP_OUT (x)

A(x)

Then A(x) expands to B MAP_OUT (x), then B (x). Now take a look at the standard:

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.

Does B (x) belong to "resulting preprocessing token sequence for more macro names to replace"? All compilers I have tried don't expand B (x) during a single scan, but what about the standard itself?

like image 329
Hirrolot Avatar asked Mar 02 '23 01:03

Hirrolot


1 Answers

Does B (x) belong to "resulting preprocessing token sequence for more macro names to replace"?

No, absolutely not. Read again:

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token sequence is then rescanned.

The preprocessing token sequence that results from parameter replacement in A(x) is precisely B MAP_OUT (x), nothing more, nothing less. This sequence is then scanned for more macros to replace, once. There is only one eligible macro to replace in there, MAP_OUT. Then the replacement of MAP_OUTis scanned, nothing is found, and the processing is resumed.

There is no indication whatsoever that B in B MAP_OUT (x) should be scanned twice.

like image 57
n. 1.8e9-where's-my-share m. Avatar answered Apr 29 '23 17:04

n. 1.8e9-where's-my-share m.