我试图理解将字符串传递给被调用函数并修改被调用函数内部数组的元素。
void foo(char p[]){
p[0] = 'a';
printf("%s",p);
}
void main(){
char p[] = "jkahsdkjs";
p[0] = 'a';
printf("%s",p);
foo("fgfgf");
}
上面的代码返回一个异常。我知道C中的字符串是不可变的,但是想知道在main中修改和修改调用函数之间有什么区别。其他日期类型会发生什么?
答案 0 :(得分:1)
我知道C中的字符串是不可变的
那不是真的。正确的版本是:修改C中的字符串文字是未定义的行为。
在main()
中,您将字符串定义为:
char p[] = "jkahsdkjs";
这是一个非文字字符数组,因此您可以对其进行修改。但是你传递给foo
的是"fgfgf"
,这是一个字符串文字。
将其更改为:
char str[] = "fgfgf";
foo(str);
没关系。
答案 1 :(得分:0)
在第一种情况下:
char p[] = "jkahsdkjs";
p
是一个使用字符串文字副本初始化的数组。由于您未指定大小,因此将根据字符串文字的长度加上空终止字符来确定。 C99标准部分6.7.8
初始化段落 14 中涵盖了这一点:
字符串数组可以由字符串文字初始化,可选 用括号括起来。字符串文字的连续字符(包括 如果有空间或数组的大小未知,则终止空字符)初始化数组的元素。
在第二种情况下:
foo("fgfgf");
您正在尝试修改未定义行为的字符串文字,这意味着程序的行为是不可预测的,并且例外是一种可能性。从C99标准草案部分6.4.5
字符串文字段落 6 (强调我的):
如果这些数组的元素具有不同的数据,则未指定 适当的价值观如果程序试图修改这样的数组,则行为是 未定义。强>
答案 2 :(得分:0)
区别在于你如何初始化p []。
char p[] = "jkahsdkjs";
这初始化为一个名为p的可写数组,自动调整大小足以包含字符串并在运行时存储在堆栈中。
然而,在以下情况下:
foo("fgfgf");
您正在传递指向实际字符串文字的指针,这些指针通常在大多数编译器中以只读方式强制执行。
其他日期类型会发生什么?
字符串文字是一种非常特殊的情况。其他数据类型(如int等)没有类似的问题,因为它们严格按值存储。