C常量字符串是否始终以空例句终止而无异常?
例如,以下C代码是否始终打印为“true”:
const char* s = "abc";
if( *(s + 3) == 0 ){
printf( "true" );
} else {
printf( "false" );
}
答案 0 :(得分:11)
如果字符串包含空字符,则该字符串只是字符串。
string 是由第一个空字符终止并包含第一个空字符的连续字符序列。 C11§7.1.11
"abc"
是一个字符串文字。它也总是包含一个空字符。 字符串文字可能包含多于1个空字符。
"def\0ghi" // 2 null characters.
但是,在下文中,x
不是字符串(它是char
的数组,没有空字符)。 y
和z
都是char
的数组,都是字符串。
char x[3] = "abc";
char y[4] = "abc";
char z[] = "abc";
使用OP的代码,s
指向字符串,字符串文字"abc"
,*(s + 3)
和s[3]
的值为0。尝试修改s[3]
是未定义的行为1)s
是const char *
和2)s
指向的数据是字符串文字。尝试修改字符串文字也是未定义的行为。
const char* s = "abc";
更深:C没有定义“常量字符串”。
该语言定义字符串文字,如"abc"
为大小为4的字符数组,其值为'a'
,'b'
,{{1 },'c'
。试图修改这些是UB。如何使用取决于具体情况。
标准C库定义 string 。
使用'\0'
,const char* s = "abc";
是指针,用于s
类型的数据。作为char
指针,使用const some_type *
修改数据是UB。 s
已初始化以指向字符串文字 s
。 "abc"
本身不是字符串。内存s
的初始点是字符串。
答案 1 :(得分:6)
简而言之,是的。 字符串常量当然是字符串,字符串按定义为0终止。
如果您使用字符串常量作为数组初始值设定项,请执行以下操作:
char x[5] = "hello";
你在x
中没有{0}终结者只是因为没有空间。
但是
char x[] = "hello";
它会在那里,x
的大小为6。
答案 2 :(得分:2)
字符串的概念被确定为由零字符终止的字符序列。序列是否可修改并不重要,即相应的声明是否具有限定符const
。
例如,C中的字符串文字具有非常量字符数组的类型。所以你可以写一些例如
char *s = "Hello world";
在此声明中,标识符s
指向字符串的第一个字符。
您可以使用字符串文字通过字符串自己初始化字符数组。例如
char s[] = "Hello world";
此声明相当于
char s[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0' };
但是在C中,您可以从字符数组的初始化中排除终止零。
例如
char s[11] = "Hello world";
虽然用作初始化程序的字符串文字包含终止零,但它从初始化中排除。结果,字符数组s
不包含字符串。
答案 3 :(得分:1)
在C中,没有像C ++和Java那样的“字符串”数据类型。
每个主管计算机科学学位课程都应该提到的重要原则:信息是符号加解释。
“字符串”通常定义为以空字节('\ 0')结尾的任何字符序列。
正在发布的“陷阱”(字符/字节数组中间值为0)只是解释的差异。将字节数组作为字符串处理而不是将其视为字节([0,255]中的数字)具有不同的应用程序。显然,如果您要打印到终端,您可能需要打印字符,直到达到空字节。如果要保存文件或在数据块上运行加密算法,则需要在字节数组中支持0。
获取“字符串”并选择将其解释为字节数组也是有效的。