宏观扩张的确切步骤是什么?

这不能按预期工作:

#define stringify(x) #x printf("Error at line " stringify(__LINE__)); 

这有效:

 #define stringify1(x) #x #define stringify(x) stringify1(x) printf("Error at line " stringify(__LINE__)); 

预处理用于扩展此类宏的优先级是什么?

扩展宏时, 只有当这些参数不受字符串化( # )或令牌粘贴( ## )运算符的影响时 ,预处理器才会扩展宏的参数。 所以,如果你有这个:

 #define stringify(x) #x stringify(__LINE__) 

然后,预处理器不会扩展__LINE__ ,因为它是字符串化运算符的参数。 但是,当你这样做时:

 #define stringify1(x) #x #define stringify(x) stringify1(x) stringify(__LINE__) 

然后,在扩展stringify ,预处理器将__LINE__扩展为当前行号,因为x不与stringify定义中的stringify化或令牌粘贴运算符一起使用。 然后它扩展了stringify1 ,我们得到了我们想要的东西。

C99标准中的相关语言来自§6.10.3.1/ 1:

在确定了调用类函数宏的参数之后,发生了参数替换。 替换列表中的参数,除非前面带有###预处理标记或后跟##预处理标记(见下文),否则在扩展其中包含的所有宏之后,相应的参数将替换该参数。 在被替换之前,每个参数的预处理标记都被完全宏替换,好像它们形成了预处理文件的其余部分; 没有其他预处理令牌可用。

条款§6.10.3.2和6.10.3.3继续分别定义###运算符的行为。