为啥使用 Visual Studio 而不是 GCC 编译时没有错误?

Posted

技术标签:

【中文标题】为啥使用 Visual Studio 而不是 GCC 编译时没有错误?【英文标题】:Why does this compile without an error with Visual Studio and not GCC?为什么使用 Visual Studio 而不是 GCC 编译时没有错误? 【发布时间】:2015-10-13 13:22:23 【问题描述】:

您知道为什么使用 Visual Studio (2012) 而不是 GCC 4.7.2 编译时没有错误吗?

我正在对棘手的源文件进行一些编译器测试。 根据接受的答案here,GCC 不应该出错(错误:/ 标记之前的预期表达式):任何紧跟换行符的反斜杠字符 () 以及换行符都会被删除。 所以,这相当于线拼接,应该作为单线进行预处理。

#include                                        \
                                                \
    "my_header_\
file_example.h" /* this is a long trailing\
                comment */

【问题讨论】:

在这里工作。也许你有 \r\n 问题? 这里有一点关于反斜杠和翻译阶段的行延续***.com/questions/7059549/…,其中一个答案是关于在反斜杠后无意中添加空格的棘手问题。 @djondal 在此处发布错误消息将有助于 1) 理解问题 2) 更好地搜索指向此处的其他有相同问题的人。 【参考方案1】:

如果您在\ 之后确实有一个行尾立即,则源代码如果正确并且应该被符合标准的编译器接受。 C99 语言草案在 5.1.1.2 翻译阶段中说:

§2: 每个反斜杠字符 (\) 的实例都被删除,紧跟一个换行符,将物理源代码行拼接成逻辑源代码行。 只有任何物理源行上的最后一个反斜杠才有资格成为此类接头的一部分。非空源文件应以换行符结尾,在任何此类拼接发生之前,该换行符之前不应紧跟反斜杠字符。

这实际上发生在第 2 阶段 预处理器执行任何 #include 之前,因此它应该根据标准被接受:

§4: 预处理指令被执行,宏调用被扩展,并且 _Pragma 一元运算符表达式被执行。如果一个字符序列 匹配通用字符的语法名称由令牌产生 连接(6.10.3.3),行为未定义。 #include 预处理 指令使命名的头文件或源文件从阶段 1 开始处理 通过第 4 阶段,递归。

但是,如果\ 和行尾之间有空格,则不会发生§2 的操作,并且会出现错误。

【讨论】:

【参考方案2】:

在宏中忽略反斜杠/换行符组合是正确的(宏延续)。但是,这发生在字符串中。反斜杠后面不是n 或其他定义的转义字母,而是0x0d0x0a,然后将其按字面意思放入字符串中。所以它试图打开的文件类似于my_header_0x0dfile_example.h

顺便说一句,知道它给出的错误很有趣。正如我在上面所怀疑的那样,它抱怨找不到文件,而不是“字符串文字中的非法'\'”。

【讨论】:

以上是关于为啥使用 Visual Studio 而不是 GCC 编译时没有错误?的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio Code - 为啥使用工作区而不是标准文件夹?

为啥 Visual Studio 2005 更喜欢“无”而不是 perforce 作为源代码控制提供程序

为啥 Visual Studio 编译器无法找到某些头文件而 intellisense 可以?

为啥按值传递 string_view?为啥 Visual Studio 不能对此进行优化?

为啥 Visual Studio 有时会使用旧代码运行?

使用 Visual Studio 9 构建的命令行应用程序不会将 *.NEF 作为输入,而使用 gcc 构建的相同应用程序会 - 为啥?