为什么在C语言中,printf("a" "b" "c")会输出abc?

6

我有以下C代码:

#include<stdio.h>
void main(){
    printf("a" "b" "c");
}

输出结果为:

abc

有人能解释一下为什么吗?

我猜测这是将"a" "b" "c"预处理成"abc",我对吗?还是说有其他原因?


2
5.1.1.2 翻译阶段 6 相邻的字符串文字标记将被连接起来。 - BLUEPIXY
1
+1 这是一个好问题,除非你知道术语,否则很难理解。 - Shafik Yaghmour
1
@ShafikYaghmour,我能恳请您保持这个问题的开放状态吗?因为它有一个更好的标题和稍微详细一些的答案。如果它被关闭了,那么搜索问题的人就找不到它了,他们可能不会看一个标题为“难道没有语法错误吗?”的问题。 - M.M
@MattMcNabb,你说得很对,我重新修改了问题和标题,现在应该更好了。 - Shafik Yaghmour
2
@MattMcNabb:即使标记为重复,人们仍然可以搜索到这个问题,我认为没有必要将所有内容分散(这就是我们拥有重复系统的原因)。它们被显示为“重复”,而不仅仅是“关闭”,这是有原因的。 - Qantas 94 Heavy
3个回答

8

相邻的字符串字面量是在第六个翻译阶段中作为一个整体连接起来的。

阶段简述(来源:C99标准,简述)

  1. 源文件中的三字符序列和多字节字符映射到源字符集
  2. \ 结尾的行被拼接
  3. 将文件解析为一组预处理标记
  4. 预处理指令被处理
  5. 字符常量和字符串字面量被迁移到执行字符集
  6. 相邻的字符串字面量被连接
  7. 编译的其余部分(不包括链接)
  8. 链接

2
那么,问题末尾 OP 所猜测的几乎是准确的,对吗? - barak manos
简而言之,这是在“预处理”期间完成的。我猜我猜对了:D。谢谢!我期待着这样的答案。 - SMR
3
取决于你是否想将第6阶段称为“预处理”。gcc -E不执行第6阶段。 - M.M
这是一个非常好的答案,我必须说。 - barak manos
@MattMcNabb 是的!感谢您提到 gcc -E,根据 printf() 的语法,我之前理解有误。现在它会给出编译错误提示。 - SMR
@SMR 值得一提的是(就像 C 标准中的任何内容一样),编译器不必按照那个顺序实际处理这些步骤——只要程序的最终输出与如果按照那个顺序处理时的输出相同即可。例如,它可以修剪空格(通常是第 7 阶段的一部分),然后连接字符串字面量,这不会有任何影响。 - M.M

4

相邻的字符串字面量在第6个翻译阶段中合并。因此"a" "b" "c"被视为"abc"字符串字面量。

如果您对这个术语不熟悉,第6阶段介于预处理和实际的“正式”编译之间。


4
要真正成为语言律师,应该使用“翻译”而不是“编译”。 - Wojtek Surowka
@WojtekSurowka:完全正确,已更正。 - Grzegorz Szpetkowski
3
好的,我会尽力进行翻译。以下是需要翻译的内容:Nice, I just learnt something new today! http://en.cppreference.com/w/cpp/language/translation_phases - Яois
说实话,问题末尾OP所猜测的是正确的(即,在预处理期间发生了这种情况),这不是事实吗? - barak manos
1
@barakmanos:那是在预处理之后。 - Deduplicator
@Deduplicator:好的,我刚才从阅读其他答案中意识到了这一点。谢谢。 - barak manos

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接