当前位置: C语言 -- 专题 -- 字符串字面量

字符串字面量

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前缀的字符串字面量和宽字符字符串字面量(前缀为Lu或者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标准未作明确说明。