我的课程告诉我,char * s是静态/只读的,所以我认为这意味着你在定义之后就无法编辑它们。 但是当我跑步时:
char* fruit = "banana"; printf("fruit is %sn", fruit); fruit = "apple"; printf("fruit is %sn", fruit);
然后编译好并给我:
fruit is banana fruit is apple
为什么? 我误解了只读是什么意思吗? 很抱歉,如果这是显而易见的,但我是新手编码,我无法在线找到答案。
显示的代码段不会更改字符串文字本身。 它只会更改指针fruit
存储的值。
你可以想象这些线条
char* fruit = "banana"; fruit = "apple";
以下方式
char unnamed_static_array_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a', ' ' }; char *fruit = &unnamed_static_array_banana[0]; char unnamed_static_array_apple[] = { 'a', 'p', 'p', 'l', 'e', ' ' }; fruit = &unnamed_static_array_apple[0];
这些语句不会更改与字符串文字对应的数组。
另一方面,如果你试图写
char* fruit = "banana"; printf("fruit is %sn", fruit); fruit[0] = 'h'; ^^^^^^^^^^^^^^ printf("fruit is %sn", fruit);
也就是说,如果您尝试使用指向它的指针(到字符串文字的第一个字符)更改字符串文字,则程序具有未定义的行为。
来自C标准(6.4.5字符串文字)
7如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。 如果程序试图修改此类数组,则行为未定义。
在程序中,表达式"banana"
表示程序映像中的字符串文字对象,即字符数组。 表达式的值是char *
类型,或“指向字符的指针”。 指针指向该数组的第一个字节,即字符'b'
。
您的char *fruit
变量也有类型“指向字符的指针”并从该表达式获取其初始值:它被初始化为指向数据的指针的副本,而不是数据本身; 它只是指向b
。
当你将"apple"
分配给fruit
,你只是将其指针值替换为另一个,因此它现在指向不同的文字数组。
要修改数据本身,您需要一个表达式,例如:
char *fruit = "banana"; fruit[0] = 'z'; /* try to turn "banana" into "zanana" */
根据ISO C标准,没有定义其行为。 可能是"banana"
数组是只读的,但这不是必需的。
C实现可以使字符串文字可写,或使其成为一个选项。
(如果你能够修改字符串文字,那并不意味着一切都很好。首先,你的程序仍然没有根据ISO C定义:它不可移植。其次,允许C编译器合并文字在同一个存储器中有共同的内容。这意味着程序中两次出现的"banana"
实际上可能是完全相同的数组。此外,程序中某处出现的字符串文字"nana"
可能是数组的后缀"banana"
发生在别处;换句话说,共享相同的存储。修改文字可能会产生惊人的效果;修改可以出现在其他文字中。)
“静态”和“只读”也不是同义词。 C中的大多数静态存储实际上是可修改的。 我们可以创建一个可修改的静态字符数组,它包含如下字符串:
/* at file scope, ie outside of any function */ char fruit[] = "banana";
要么:
{ /* in a function */ static fruit[] = "banana";
如果我们省略数组大小,它将从初始化字符串文字自动resize,并包含空终止字节的空间。 在函数中,我们需要static
将数组放入静态存储,否则我们得到一个局部变量。
这些数组可以修改; fruit[0] = 'z'
是明确定义的行为。
此外,在这些情况下, "banana"
不表示字符数组。 arrays是可变的fruit
; "banana"
表达式只是表示数组初始值的一段语法:
char *fruit = "banana"; // "banana" is an object in program image // initial value is a pointer to that object char fruit_array[] = "apple"; // "apple" is syntax giving initial value
基本上,当你表演时
char* fruit = "banana";
你设置指针fruit
到“香蕉”的第一个字母。 打印出来时,C基本上从’b’开始并保持打印字母,直到它在结尾处遇到