正如名称literal 本身所暗示的字符串文字是用双引号括起来的字符序列。此字符序列隐式附加一个终止零。
所以任何用双引号括起来的字符都是字符串文字的一部分。
当字符串字面量用于初始化字符数组时,它的所有字符(包括终止零)都用作字符数组相应元素的初始化器。
每个字符串文字依次具有字符数组的类型。
例如,C 中的这个字符串文字 "Hello\0Hi" 的类型为 char[9]:引号中包含 8 个字符加上隐式终止零。
所以在内存中这个字符串字面量是这样存储的
{ 'H', 'e', 'l', 'l', 'o', '\0', 'H', 'i', '\0' }
运算符sizeof 返回对象占用的字节数。所以对于上面的字符串字面量,sizeof 运算符将返回值9——它是字面量在内存中占用的字节数。
如果你写了"Hello\0Hi",那么编译器本身可能不会只是从文字中删除这部分Hi。它必须将它与用引号括起来的文字的其他字符一起存储在内存中。
sizeof 运算符返回 C 中任何对象的字节大小,而不仅仅是字符数组。
一般来说,字符数组可以存储任何原始数据,例如从二进制文件中读取的一些二进制数据。在这种情况下,用户和程序不会像字符串一样考虑此数据,因此结果的处理方式与字符串不同。
标准 C 函数strlen 是专门为字符数组编写的,用于查找字符数组中存储字符串的长度。它不知道数组中存储了哪些数据以及它们是如何写入其中的。它所做的只是搜索字符数组中的第一个零字符并返回字符数组中零字符之前的字符数。
您可以在一个字符数组中顺序存储多个字符串。例如
char s[12];
strcpy( s, "Hello" );
strcpy( s + sizeof( "Hello" ), "World" );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
如果你要像这样定义一个二维数组
char t[2][6] = { "Hello", "World" };
那么它在内存中的存储方式与上面的一维数组相同。所以你可以写
char *s = ( char * )t;
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
另一个例子。标准 C 函数strtok 可以将存储在字符数组中的一个字符串拆分为多个字符串,用零字节替换用户指定的分隔符。结果字符数组将包含多个字符串。
例如
char s[] = "Hello World";
printf( "%zu\n", sizeof( s ) ); // outputs 12
strtok( s, " " );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
printf( "%zu\n", sizeof( s ) ); // outputs 12
最后一个 printf 语句将输出相同的值,等于 12,因为数组占用相同的字节数。只需将分配给数组的内存中的一个字节从' ' 更改为'\0'。