当前位置: 首页 > 知识库问答 >
问题:

为什么这个宏被替换为20而不是10?

桂阳文
2023-03-14
1. #define NUM 10
2. #define FOO NUM
3. #undef NUM
4. #define NUM 20
5. 
6. FOO

当我只运行预处理器时,输出文件包含20。

然而,据我所知,预处理器只是进行文本替换。所以这就是我认为正在发生的事情(这显然是错误的,但idky):

  1. NUM被定义为10

所以我认为输出应该是10而不是20。有什么能解释出哪里出了问题吗?

共有3个答案

施自怡
2023-03-14

在:

FOO

预处理器将把它替换为NUM,然后将NUM替换为它当前的定义,即20

最初的四行相当于:

#define FOO NUM 
#define NUM 20
秦德海
2023-03-14

为了从标准中收集所有相关规范,我从评论线程中提取了这些信息,并根据N4527草案(两个标准中的规范性文本相同)添加了C节编号。标准在这个问题上是绝对明确的。

>

  • #定义预处理器指令不进行宏替换。

    (C11§6.10¨7;C§16[cpp]¨6):除非另有说明,否则预处理指令中的预处理令牌不受宏扩展的约束。

    用替换文本替换宏后,将重新扫描新文本。如果在程序中的该点上有标记的活动宏定义,则替换中的预处理器标记将扩展为宏。

    (C11§6.10.3¨9;C§16.3[cpp.替换]¨9)表格的预处理指令

    定义标识符替换列表新行

    定义一个类似对象的宏,该宏使宏名称的每个后续实例都被构成指令其余部分的预处理标记的替换列表替换。然后重新扫描替换列表以获得更多宏名称,如下所示。

    #定义之后的行开始,宏定义处于活动状态,直到宏名称的#UNDf或文件末尾。

    (C11§6.10.3.5¨1;C§16.3.5[cpp.范围]¨1)宏定义持续(独立于块结构),直到遇到相应的#unde指令,或者(如果没有遇到)直到预处理翻译单元结束。在翻译阶段4之后,宏定义没有意义。

    如果我们看看这个节目:

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

    我们看到第1行中的NUM的宏定义一直持续到第3行。这些行中没有可替换的文本,因此从未使用该定义;因此,该计划实际上与以下内容相同:

    #define FOO NUM
    #define NUM 20
    FOO 
    

    在这个程序中,在第三行,有一个FOO的活动定义,带有替换列表NUM,对于NUM,带有替换列表20FOO被替换为其替换列表,使其NUM,然后再次扫描宏,导致NUM被替换为其替换列表20。该替换再次重新扫描,但没有定义的宏,因此最终结果是令牌20留在转换阶段5中处理。

  • 段兴为
    2023-03-14

    文本替换是在使用宏的地方完成的,而不是在您编写#定义的地方。在您使用FOO时,它将FOO替换为NUMNUM当前定义为20

     类似资料:
    • 我的讲师在课堂上问过我这个问题,我想知道为什么是宏而不是函数?

    • 问题内容: 我们尝试使用以下Java代码从字符串转换为: 我们得到一个长度为22个字节的字节数组,我们不确定此填充来自何处。如何获得长度为20的数组? 问题答案: 亚历山大(Alexander)的答案解释了为什么存在它,但没有解释如何摆脱它。您只需要在编码名称中指定所需的字节序即可:

    • 问题内容: 对于Java的处理方式以及涉及到的数字和其他类型的数字,我有些困惑。例如: 输出(也许您应该先猜测一下): 这不能编译是可以预料的,是不同的对象。 令我有些惊讶的是,默认情况下9是an ,并且1)甚至没有编译。请注意,您不能将放入期望使用的方法中,但是在这里它们是相等的。 由于两个相同的原因,这令人惊讶,但似乎更糟。 不足为奇,因为自动装箱到和。 不足为奇,因为不同类中的对象不应该是。

    • 因此,我想要一个代码,使我的HTML列表在冒号之前加粗。所以我搜索了一个我选择使用的代码。在堆栈溢出中看到一个代码:https://stackoverflow.com/a/46855744/15163136.我没有使用for循环,而是使用foreach循环。 但唯一的问题是我不理解和

    • 在Julia中,打印格式化字符串的语法如下: 为什么是宏而不是函数?这样它就可以接受不同数量的参数了吗?

    • 我以前使用过: 要创建对象,请执行以下操作: 然而,这似乎不再有效。编译器报告: 宏定义发生了什么变化,使其不再工作? 下面的基本示例效果良好: 这似乎是对{T:ident,$(…),}的一些改变是否正在处理扩展? 这到底是怎么回事?