?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
構(gòu)造一個(gè)指定字符數(shù)組類型的未命名對象,用于需要在源代碼中嵌入字符串時(shí)使用。
" s-char-sequence " | (1) | |
---|---|---|
u8 " s-char-sequence " | (2) | (since C11) |
u " s-char-sequence " | (3) | (since C11) |
U " s-char-sequence " | (4) | (since C11) |
L " s-char-sequence " | (5) |
其中
S-炭序列 | - | 零個(gè)或多個(gè)字符,每個(gè)字符可以是源字符集中的多字節(jié)字符(不包括(“),\和換行符),也可以是字符轉(zhuǎn)義,十六進(jìn)制轉(zhuǎn)義,八進(jìn)制轉(zhuǎn)義或統(tǒng)一字符名稱(自C99開始)在轉(zhuǎn)義序列中。 |
---|
1)字符串文字:文字的類型是char[]
,數(shù)組中的每個(gè)字符都是使用執(zhí)行字符集從s-char-sequence中的下一個(gè)字符初始化的。
2)UTF-8字符串文字:文字的類型是char[]
,數(shù)組中的每個(gè)字符都是使用UTF-8編碼從s-char-sequence中的下一個(gè)多字節(jié)字符初始化的。
3)16位寬字符串文字:文字的類型是char16_t[]
,數(shù)組中的每個(gè)char16_t元素都被初始化,就好像通過mbrtoc16
在實(shí)現(xiàn)定義的區(qū)域設(shè)置中執(zhí)行一樣。
4)32位寬的字符串文字:文字的類型是char32_t[]
,數(shù)組中的每個(gè)char32_t元素都被初始化,就好像通過mbrtoc32
在實(shí)現(xiàn)定義的區(qū)域設(shè)置中執(zhí)行一樣。
5)寬字符串文字:文字的類型是wchar_t[]
,數(shù)組中的每個(gè)wchar_t元素被初始化,就好像通過mbstowcs
在實(shí)現(xiàn)定義的區(qū)域設(shè)置中執(zhí)行一樣。
首先,在翻譯階段6(宏擴(kuò)展之后),將相鄰的字符串文字(即僅由空白分隔的字符串文字)連接起來。
只有兩個(gè)窄或兩個(gè)寬字符串可以連接在一起。 | (直到C99) |
---|---|
如果一個(gè)文字沒有前綴,那么結(jié)果字符串文字的寬度/編碼由前綴文字指定。如果兩個(gè)字符串文字具有不同的編碼前綴,則連接是實(shí)現(xiàn)定義的。L“Δx=%”PRId16 //在階段4,PRId16在階段6擴(kuò)展為“d”// L“Δx=%”和“d”形成L“Δx=%d” | (自C99以來) |
其次,在翻譯階段7,將終止空字符添加到每個(gè)字符串文字中,然后每個(gè)文字初始化一個(gè)靜態(tài)存儲持續(xù)時(shí)間和長度的未命名數(shù)組,以便足以容納字符串文字的內(nèi)容加上一個(gè)空終止符。
char* p = "\x12" "3"; // creates a static char[3] array holding {'\x12', '3', '\0'} // sets p to point to the first element of the array
字符串文字是不可修改的(事實(shí)上可以放在只讀存儲器中.rodata
)。如果程序試圖修改由字符串文字形成的靜態(tài)數(shù)組,則行為是不確定的。
char* p = "Hello";p[1] = 'M'; // Undefined behavior
對于相同的字符串文字來說,既不要求也不禁止在存儲器中引用相同的位置。而且,重疊的字符串文字或者是其他字符串文字的子字符串的字符串文字可以組合。
"def" == 3+"abcdef"; // may be 1 or 0, implementation-defined
字符串文字不一定是一個(gè)字符串; 如果字符串文字含有空字符,則表示包含多個(gè)字符串的數(shù)組:
char* p = "abc\0def"; // strlen(p) == 3, but the array has size 8
如果一個(gè)有效的十六進(jìn)制數(shù)字在字符串文字中出現(xiàn)十六進(jìn)制轉(zhuǎn)義,它將無法編譯為無效轉(zhuǎn)義序列,但字符串連接可以用作解決方法:
//char* p = "\xfff"; // error: hex escape sequence out of rangechar* p = "\xff""f"; // okay, the literal is char[3] holding {'\xff', 'f', '\0'}
字符串文字可用于初始化數(shù)組,如果數(shù)組大小小于字符串文字的大小,則會忽略空終止符:
char a1[] = "abc"; // a1 is char[4] holding {'a', 'b', 'c', '\0'}char a2[4] = "abc"; // a2 is char[4] holding {'a', 'b', 'c', '\0'}char a3[3] = "abc"; // a3 is char[3] holding {'a', 'b', 'c'}
字符串文字(1)和寬字符串文字(5)的編碼是實(shí)現(xiàn)定義的。例如,GCC與選擇它們的命令行選項(xiàng) -fexec-charset
和-fwide-exec-charset
。
#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <uchar.h>#include <locale.h>int main(void){ char s1[] = "a貓?"; // or "a\u732B\U0001F34C" char s2[] = u8"a貓?"; char16_t s3[] = u"a貓?"; char32_t s4[] = U"a貓?"; wchar_t s5[] = L"a貓?"; setlocale(LC_ALL, "en_US.utf8"); printf(" \"%s\" is a char[%zu] holding { ", s1, sizeof s1 / sizeof *s1); for(size_t n = 0; n < sizeof s1 / sizeof *s1; ++n) printf("%#x ", +(unsigned char)s1[n]); puts(" }"); printf("u8\"%s\" is a char[%zu] holding { ", s2, sizeof s2 / sizeof *s2); for(size_t n = 0; n < sizeof s2 / sizeof *s2; ++n) printf("%#x ", +(unsigned char)s2[n]); puts(" }"); printf(" u\"a貓?\" is a char16_t[%zu] holding { ", sizeof s3 / sizeof *s3); for(size_t n = 0; n < sizeof s3 / sizeof *s3; ++n) printf("%#x ", s3[n]); puts(" }"); printf(" U\"a貓?\" is a char32_t[%zu] holding { ", sizeof s4 / sizeof *s4); for(size_t n = 0; n < sizeof s4 / sizeof *s4; ++n) printf("%#x ", s4[n]); puts(" }"); printf(" L\"%ls\" is a wchar_t[%zu] holding { ", s5, sizeof s5 / sizeof *s5); for(size_t n = 0; n < sizeof s5 / sizeof *s5; ++n) printf("%#x ", s5[n]); puts(" }");}
可能的輸出:
"a貓?" is a char[9] holding { 0x61 0xe7 0x8c 0xab 0xf0 0x9f 0x8d 0x8c 0 }u8"a貓?" is a char[9] holding { 0x61 0xe7 0x8c 0xab 0xf0 0x9f 0x8d 0x8c 0 } u"a貓?" is a char16_t[5] holding { 0x61 0x732b 0xd83c 0xdf4c 0 } U"a貓?" is a char32_t[4] holding { 0x61 0x732b 0x1f34c 0 } L"a貓?" is a wchar_t[4] holding { 0x61 0x732b 0x1f34c 0 }