C字符串:简单的问题

Ock*_*zor 6 c c++ string

我在下面初始化了三个变量:

char c1[] = "Hello";
char c2[] = { 'H', 'e', 'l', 'l', 'o', '\0'};
char* c3 = "Hello";
Run Code Online (Sandbox Code Playgroud)

我知道c1和c2是相同的,并且它们都是字符串,因为它们被\ 0终止.但是,c3与c1和c2不同.这是因为c3不以\ 0结尾吗?这是否意味着c3不是字符串?如果c3不是字符串,那么为什么不 printf("%s", c3);给出错误?谢谢!

编辑:

有没有理由可以修改c1和c2,但c3不能?

pax*_*blo 10

就C而言,与其他人之间最相关的区别c3是你不能尝试修改底层角色c3.我经常觉得这样想是有帮助的:

char *xyz = "xyz";
Run Code Online (Sandbox Code Playgroud)

将在堆栈上创建一个可修改的指针,并使其指向不可修改的字符序列{'x','y','z','\0'}.另一方面,

char xyz[] = "xyz";
Run Code Online (Sandbox Code Playgroud)

将在堆栈上创建一个可修改的数组,该数组足以容纳字符序列{'x','y','z','\0'},然后将该字符序列复制到其中.然后可以修改数组内容.请记住,标准没有说明堆栈,但这通常是如何完成的.毕竟,它只是一种记忆辅助工具.

形式上,c3是一个指向字符串文字的指针,c1而且c2它们都是字符数组,它们都碰巧以空字符结尾.当它们被传递给类似的函数时printf,它们会衰减到指向数组的第一个元素的指针,这意味着它们将c3在该函数内被相同地处理(实际上它们在很多情况下会衰减,请参阅下面的c99中的第三个引用例外).

C99的相关部分6.4.5 String literals解释了为什么不允许您修改c3指向的内容:

如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的.如果程序试图修改此类数组,则行为未定义.

为什么它确实有一个空终止:

在转换阶段7中,将值为零的字节或代码附加到由字符串文字或文字产生的每个多字节字符序列.

6.3.2.1 Lvalues, arrays, and function designators6.3 Conversions状态:

除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将类型为''array of type''的表达式转换为类型为''指针的表达式type''指向数组对象的初始元素,而不是左值.如果数组对象具有寄存器存储类,则行为未定义.


iam*_*ind 5

第一点,

char* c3 = "Hello"; // may be valid C, but bad C++!
Run Code Online (Sandbox Code Playgroud)

是一种容易出错的风格,所以不要使用它.而是使用,

const char* c3 = "Hello";
Run Code Online (Sandbox Code Playgroud)

这是一个有效的代码.指针c3指向"Hello"存储字符串的位置的地址.但是你不能 像以前那样修改*c3(即内容c3)(如果你这样做,那就是一个未定义的行为).