在C语言中尝试访问字符串中的字符时出现总线错误。

6

我曾经多次使用这行代码(更新:当字符串是函数参数时!),但是现在尝试这么做时,我遇到了总线错误(无论是使用gcc还是clang)。我正在重现最简单的可能代码;

char *string = "this is a string";
char *p = string;
p++;
*p='x'; //this line will cause the Bus error
printf("string is %s\n",string);

为什么我无法使用p指针更改字符串的第二个字符?


1
gcc有一个选项-Wwrite-strings,它会通过将字符串设置为const char []来警告您更改字面字符串的行为。请注意,标准说字面字符串是char[](实际上是“只读char[]”),但使它们成为常量会使您的编译器(更)不符合标准。 - pmg
1个回答

14

您正在尝试修改只读内存(其中存储了该字符串字面值)。如果您需要修改该内存,可以使用字符数组。

char str[] = "This is a string";
str[0] = 'S'; /* works */
我已经多次使用了这行代码...
我非常希望不是这样。最好的情况下,您会收到一个segfault(我之所以这么说是因为尝试修改只读内存是未指定行为,在这种情况下可以发生任何事情,并且崩溃是可能发生的最好的事情)。
当您声明指向字符串文字的指针时,它指向数据段中的只读内存(如果您喜欢,请查看汇编输出)。将类型声明为char[]将该文本复制到函数堆栈上,从而允许在需要时对其进行修改。

1
尝试修改字符串常量是未定义行为。它可能看起来可以工作,但当然不能保证。 - dreamlax
“在最好的情况下,你会得到一个段错误” - 实际上,这个说法并不完全正确。未定义行为是未定义的,有时候这意味着它像预期的那样工作 :-) 有很多嵌入式芯片没有内存保护。并不是说你的“答案”是错的,因为问题标记了Linux(所以+1),只是某个特定的观点并不一定在所有情况下都是正确的。 - paxdiablo
因此,“At best”部分的意思是最好的情况下。 - Ed S.
你很幸运能得到一个段错误。 - Ed S.
1
段错误是最好的情况。最坏的情况是它会默默地“工作”,并更改程序中其他地方具有相同内容和共享相同存储的常量字符串的值。 - R.. GitHub STOP HELPING ICE
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接