字符串字面值的编译

Compilation of string literals

本文关键字:编译 字面值 字符串      更新时间:2023-10-16

为什么两个由空格,制表符或"n"分隔的字符串字面值可以编译而没有错误?

int main()
{
   char * a = "aaaa"  "bbbb";
} 

"aaaa"是一个字符*"bbbb"是一个字符*

没有特定的连接规则来处理两个字符串字面值。很明显,下面的代码在编译时给出了一个错误:

#include <iostream>
int main()
{
   char * a = "aaaa";
   char * b = "bbbb";
   std::cout << a b;
}

这种连接对所有编译器都是通用的吗?"aaaa"的无效终止在哪里?"aaaabbbb"是一个连续的RAM块吗?

如果你在第6阶段看到这个翻译阶段引用,它会:

相邻的字符串字面值被连接起来。

这正是这里发生的事情。您有两个相邻的字符串字面值,它们被连接成一个字符串字面值。

这是标准行为。

它只适用于字符串字面值,而不是两个指针变量,正如您注意到的。

在此语句中

char * a = "aaaa"  "bbbb";

在语法分析之前的某个编译步骤中,编译器将相邻的字符串字面值视为一个字面值。

对于编译器来说,上面的语句等价于

char * a = "aaaabbbb";

即编译器只存储一个字符串字面值"aaaabbbb"

根据C(和c++)标准的规则将相邻的字符串字面值连接起来。但是相邻的标识符(即变量ab)不存在这样的规则。

引用c++ 14 (N3797 draft),§2.14.5:

在翻译阶段6(2.2)中,相邻的字符串字面值为连接。如果两个字符串字面值具有相同的编码前缀,结果连接的字符串字面值具有该编码前缀。如果一个字符串字面值没有编码前缀,它被视为字符串与另一个操作数相同的编码前缀的字面值。如果是UTF-8字符串字面值标记与宽字符串字面值标记相邻程序格式不良。任何其他连接都是条件支持与实现定义的行为。

在C和c++中,将相邻的字符串字面值编译为单个字符串字面值。例如:

"Some text..." "and more text"

等价于:

"Some text...and more text"

由于历史原因:

最初的C语言是在1969-1972年设计的,当时计算机仍然由80列打孔卡片主导。它的设计者使用了80列设备,如ASR-33电传打字机。这些设备不会自动换行文本,因此有必要将源代码保持在80列以内。在最终转向自由格式之前,Fortran和Cobol有明确的延续机制来做到这一点。

对于Dennis Ritchie(我猜)来说,这是一个聪明的举动,他意识到语法中没有歧义,并且通过让编译器将相邻的文字字符串连接起来的简单权能,可以使长ASCII字符串适合80列。无数的C程序员都很感激这个小功能。

一旦有了这个功能,为什么要把它删除呢?它不会引起悲伤,而且常常很方便。我希望更多的语言都有这个词。现代的趋势是使用三引号或其他符号来扩展字符串,但是C中这个特性的简单性从来没有被超越过。

并排放置的字符串字面值在翻译阶段6(在预处理器之后)被连接起来。也就是说,"Hello," " world!"产生(单个)字符串"Hello, world!"。如果两个字符串具有相同的编码前缀(或两者都没有),则结果字符串将具有相同的编码前缀(或没有前缀)。

(源)