字符串字面值的编译
Compilation of string literals
为什么两个由空格,制表符或"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++)标准的规则将相邻的字符串字面值连接起来。但是相邻的标识符(即变量a
和b
)不存在这样的规则。
引用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!"
。如果两个字符串具有相同的编码前缀(或两者都没有),则结果字符串将具有相同的编码前缀(或没有前缀)。
(源)
- VB6和c++布尔字面值
- 为什么添加两个字符串字面值不使用操作符+
- 在编译时定义字符串/char字面值
- c++的字符串字面值如何存储在内存中?
- 为什么可以向字符串字面值添加整数?
- 用户定义字面值如何与数字分隔符一起使用
- 可修改字符串字面值的用例
- c++ constexpr vs宏,字符串字面值vs整数
- 字符串对字符串字面值的优化不够
- 是否有可能合法地重载字符串字面值和const char*
- UnicodeString /字符串字面值vs十六进制值
- 为什么将指针的内容修改为字符串字面值是错误的?
- 可变char模板的用户定义字面值
- c++: Std::cout缓冲区错误?对字符串变量和字符串字面值使用std::cout导致输出混乱
- 不能定义用户定义的字面值
- C/ c++预处理器中的宏参数字符串化为宽字符串字面值
- 如何在c++中编写八进制浮点字面值
- 是否有可能获得包含字面值的字符串的长度
- c++ 11编译时调用printf的格式字符串字面值构造
- 字符串字面值的编译