新的__LINE__什么时候开始?

fre*_*low 9 c++ macros newline c-preprocessor

我不明白以下程序的输出:

#include <iostream>

#define FOO std::cout << __LINE__ << ' ' \
                      << __LINE__ << '\n';
int main()
{
    FOO

    std::cout << __LINE__ << ' ' \
              << __LINE__ << '\n';
}
Run Code Online (Sandbox Code Playgroud)

第一个输出是77,表示扩展FOO是单个逻辑行,但第二个输出是910,表示两个不同的逻辑行.为什么会有区别?

ybu*_*ill 5

因为

1:  #include <iostream>
2: 
3:  #define FOO std::cout << __LINE__ << ' ' \
4:                        << __LINE__ << '\n';
5:  int main()
6:  {
7:      FOO // the first two __LINE__s come from here, that's one line of code
8: 
9:      std::cout << __LINE__ << ' ' \ // 3rd __LINE__ comes from here
10:              << __LINE__ << '\n'; // 4th __LINE__ comes from here
11: }
Run Code Online (Sandbox Code Playgroud)

__LINE__ 扩展到物理线,而不是逻辑线:

在将源文件处理为当前令牌时,当前源行的行号比在转换阶段1(2.2)中读取或引入的换行符号的数量大1.

虽然结束的行在\翻译阶段2中连接在一起.

另一个唯一的逻辑实现是打印3和4来调用FOO,但这似乎不是很有用.

您还可以通过以下方式查看:__LINE__与任何其他宏没有任何不同.它只是由编译器在每一行的开头自动更新.所以代码是这样解释的:

#include <iostream>

#define __LINE__ 3
#define FOO std::cout << __LINE__ << ' ' \
                      << __LINE__ << '\n';
int main()
{
#define __LINE__ 7
    FOO

#define __LINE__ 9
    std::cout << __LINE__ << ' ' \ // Yeah, you're right
#define __LINE__ 10
             << __LINE__ << '\n';
}
Run Code Online (Sandbox Code Playgroud)

这不是有效的代码,但它演示了事情是如何工作的.应用通常的宏扩展规则,您将获得您已获得的输出.

  • 另请注意,当展开包含换行符的宏时,展开的宏不包含换行符.换行符在宏*定义*中被转义,因此"实际宏"没有它.这与将`\n`放在字符串中相反.因此,您可以将"__LINE__"视为在其他宏替换后被替换. (2认同)