字符串字面量
ISO/IEC 9899:2018标准对字符串字面量的语法作了规定,其格式如下所示:
encoding-prefixopt"s-char-sequenceopt"
其中encoding-prefix是编码前缀;s-char-sequence是字符序列,两者都是可选的。编码前缀表示字符串字面量所用字符集,ISO/IEC 9899:2018标准支持的编码前缀如下表所示:
前缀 | 描述 | 对应类型 |
无 | 字符字符串字面量。 |
char * |
u8 | UTF-8字符串字面量。 |
char * |
L | 宽字符字符串字面量。 |
wchar_t * |
u | 16位宽字符字符串字面量。 |
char16_t * |
U | 32位宽字符字符串字面量。 |
char32_t * |
字符序列可以由源字符集的任何成员(双引号、反斜杠、换行符除外。)或者转义序列构成;双引号、反斜杠、换行符可以使用转义序列来表示,例如:\"、\\、\n。如果缺省字符序列,则表示字符串字面量为空。
字符串字面量的拼接
如果字符串字面量太长,C语言允许将字符串字面量分成多行来表示,一种方法就是在每行末尾使用反斜杠,例如:
printf("Genius is one percent inspiration and ninety-nine percent perspiration.\ Without the one percent of inspiration,\ all the perspiration in the world is only a bucket of sweat.\ -- Thomas Edison");
字符串字面量会延续到下一行;每行开始处如果有空白字符,都是字符串字面量的一部分。使用这种方法,反斜杠后面只能有换行符,不能有其它字符。编译时编译器会将多行代码拼接成一个字符串字面量。
字符串字面量的串联
在编译阶段的第6个步骤,编译器会将相邻的字符串字面量串联成一个字符串字面量,例如:
"x" "y" "z"
将串联成
"xyz"
串联字符串字面量时,如果有一个字符串字面量有前缀,结果字符串字面量将具有相同的前缀,例如:
L"x" "y" "z" L"x" L"y" "z"
上述两个例子的串联结果是相同的,均为
L"xyz"
相邻字符串字面量序列如果同时包含u8前缀的字符串字面量和宽字符字符串字面量(前缀为L、u或者U),这种行为是非法的,例如:
L"x" "y" u8"z" //非法。
不同前缀的宽字符字符串字面量能否串联将由实现定义;如果可以串联,结果字符串字面量的处理也将由实现定义。
字符串字面量拼接和串联的比较
拼接和串联允许将一个长字符串字面量拆分成多行来表示,但在合并成一个字符串字面量时这两种方法还是有差异的,差异的主要原因是它们发生的先后顺序不一样。代码拼接发生在源字符转换成执行字符之前,相邻字符串字面量串联发生在源字符转换成执行字符之后。下面通过一个具体例子比较一下它们的差异。
printf("\12\ 3"); printf("\12" "3");
将输出:
S
3
对于第一个输出是先拼接后转换,所以输出转义序列\123,在ASCII字符集中对应的是大写字母S。对于第二个输出是先转换后串联,在ASCII字符集中转义序列\12对应的是换行符,所以第二个输出是先输出换行符,再输出3。
字符串字面量的存储
在编译阶段的第7个步骤,编译器会在字符串字面量的末尾添加一个空字符('\0')(注:由于这个原因,字符串字面量不一定是字符串。),然后将这个序列存入一个具有静态存储期限的数组。以字符串字面量"China"为例,其存储形式如下所示:
C | h | i | n | a | \0 |
数组中存有6个字符,即'C'、'h'、'i'、'n'、'a'、'\0',每个字符占1个字节空间。
如果字符串字面量为空,将只存储1个空字符。
由于字符串字面量的存储特点,字符串字面量可以用作地址运算符(&)和下标运算符([])的操作数,例如:
printf("%p\n", &"China"); printf("%c\n", "China"[1]);
如果试图修改字符串字面量,其行为是未定义的,例如:
"China"[0] = 'c'; //未定义行为。
值相同的字符串字面量是否具有相同的存储地址,ISO/IEC 9899:2018标准未作明确说明。