我开始在vim编码 C ,我遇到了一些问题。
反斜杠用于连接线,但是当我尝试写入时:
ret\
urn 0;
我得到了
return
0;
当我在urn;
之前添加空格时,它会保持不加入的状态。
ret\
urn 0;
它保持这样。
为什么在第二种情况下我不会return 0;
而是
ret
urn 0;
CPP输出:
命令:
gcc -E -Wall -Wextra -Wimplicit -pedantic -std=c99 main.c -o output.i
GCC 5.4, Vim 7.4
答案 0 :(得分:3)
-E
输出未由标准正式指定。它是几个不同设计约束之间的工程权衡,其中相关的两个是:
-E
输出反馈回gcc -fpreprocessed
- 这是-save-temps
所做的)与正常情况相同的 pp-tokens 序列(没有{ {1}})。 (有关pp-token的定义,请参阅C99第6.4节。)以下是您的示例:
-E
反斜杠 - 换行符将ret\
urn 0;
和ret
组合成一个pp-token,因此必须在输出中的一行上一起出现。但是,urn
和0
应继续保留在其原始行和列上,以便诊断准确无误。所以你得到了
;
插入空格以将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;\