在C中连接线[奇怪的输出与文档不兼容]

时间:2017-01-18 08:57:10

标签: c gcc vim c-preprocessor

我开始在vim编码 C ,我遇到了一些问题。

反斜杠用于连接线,但是当我尝试写入时:

ret\
urn 0;

我得到了

return
    0;

当我在urn;之前添加空格时,它会保持不加入的状态。

ret\
   urn 0;

它保持这样。

为什么在第二种情况下我不会return 0;而是

ret
   urn 0;

代码: enter image description here

CPP输出:

enter image description here

命令:

gcc -E -Wall -Wextra -Wimplicit -pedantic -std=c99 main.c -o output.i

GCC 5.4, Vim 7.4

3 个答案:

答案 0 :(得分:3)

-E输出未由标准正式指定。它是几个不同设计约束之间的工程权衡,其中相关的两个是:

    必须根据需要插入或删除
  • 空格,以便"编译器正确" (想象一下将-E输出反馈回gcc -fpreprocessed - 这是-save-temps所做的)与正常情况相同的 pp-tokens 序列(没有{ {1}})。 (有关pp-token的定义,请参阅C99第6.4节。)
  • 在最大程度上,令牌应出现在原始源代码中的相同行和列位置,以便错误消息和调试信息尽可能准确。

以下是您的示例:

-E

反斜杠 - 换行符将ret\ urn 0; ret组合成一个pp-token,因此必须在输出中的一行上一起出现。但是,urn0应继续保留在其原始行和列上,以便诊断准确无误。所以你得到了

;

插入空格以将return 0; 保留在原始列中。

0

此处反斜杠换行符后面紧跟空格,因此ret\ urn 0; ret 必须合并,因此,如果诊断最准确的话一切都保持原来的状态,输出是

urn

看起来像反斜杠换行符完全没有效果。

您可能会发现ret urn 0; 的输出不那么令人惊讶。 gcc -E -P告诉预处理器不要试图保留令牌位置(并且还会关闭输出中以-P开头的所有行)。您的示例会在#模式下生成return 0;ret urn 0;,所有这些都在一行上。

最后,提出一条建议:如果你永远不会在中间用反斜杠换行分割你的代码,那么每个人都必须阅读你的代码(包括你自己六个月后)。 ,除了非常长的字符串文字。如果它是从今天开始设计的,那么这种遗留错误不会被包含在语言中。

答案 1 :(得分:1)

空格是一个标记分隔符。仅仅因为你拆分线并不意味着将忽略空格。

编译器看到的内容类似于ret urn;。哪个是无效的C,因为它可能之前没有定义过两个令牌,也不是有效的表达式。

关键字必须写为没有空格的单个标记。

现在,当你这样做时:

  ret\
urn;

在早期翻译阶段删除后跟换行符的反斜杠,并追加后续行。如果该行在开头没有空格,则结果是编译器理解为关键字return的有效标记。

长话短说,你似乎在询问specific behavior for GCC。这似乎是一个编译器错误。自clang does the expected thing起(尽管行数保持不变):

clang -E -Wall -Wextra -Wimplicit -pedantic -std=c99 -x c main.cpp
# 1 "main.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 316 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "main.cpp" 2
int main(void) {
  ret urn 0;

}

然而,这似乎并不重要,因为在这种特殊情况下,代码无论如何都会无效。

答案 2 :(得分:0)

\上跟随换行符的C预处理器的行为是从输入中删除这两个字节。这是在解析的早期阶段完成的。然而,预处理器保留了它看到的每个令牌的原始行号,并尝试在单独的行上输出令牌,以便编译器为后续的编译阶段发出正确的诊断。

输入:

ret\
urn 1;

它可能会产生:

#line 1 "myfile.c"
return
#line 2 "myfile.c"
 1;

它可以缩短为

return
 1;

请注意,您可以使用转义换行符在任意位置拆分任何输入行:

#inclu\
de <st\
dio.h>\

"Hello word\\
n"

for (i = 0; i < n; i+\
+)

ret\
\
\
urn;

\
r\
et\
urn\
123;\