为什么以下代码中的分段错误?

我在维基百科上看到了这个

int main(void) { char *s = "hello world"; *s = 'H'; } 

当编译包含此代码的程序时,字符串“hello world”被放置在标记为只读的程序可执行文件的部分中; 加载时,操作系统将其与其他字符串和常量数据放在只读的内存段中。 执行时,变量s设置为指向字符串的位置,并尝试通过变量将H字符写入内存,从而导致分段错误**

我不知道为什么字符串被放在只读段中。请有人解释一下。

字符串文字存储在只读内存中,这就是它的工作原理。 您的代码使用初始化的指针指向存储字符串文字的内存,因此您无法有效地修改该内存。

要在可修改的内存中获取字符串,请执行以下操作:

 char s[] = "hello world"; 

那你很好,因为现在你只是使用常量字符串来初始化一个非常数数组。

两者之间有很大的不同:

 char * s = "Hello world"; 

 char s[] = "Hello world"; 

在第一种情况下, s是指向您无法更改s内容的指针。 它存储在只读存储器中(通常位于应用程序的代码部分)。

在后一种情况下,您可以在读写内存(通常是普通RAM)中分配一个可以修改的数组。

  • 当你这样做: char *s = "hello world"; 然后s指向 代码部分中 的内存的指针 ,因此您无法更改它。

  • 当你这样做: char s[] = "Hello World"; 然后s堆栈上的字符数组 ,因此您可以更改它。

如果您不希望在程序期间更改字符串,最好这样做: char const *s = ....; 。 然后,当您尝试更改字符串时,您的程序将不会因分段错误而崩溃 ,它将出现编译器错误 (这要好得多)。

首先要对指针有一个很好的理解,我会给你一个简短的演示:

首先让我们逐行分析您的代码。 让我们从主要开始

char * s =“Some_string”;

首先,你声明一个指向char变量的指针,现在* s是内存中的一个地址,如果你试图改变它的内存值,C会踢你,这是非法的,所以你最好声明一个字符数组,然后分配s到它的地址,然后改变s。

希望你能得到它。 有关进一步参考和详细了解,请参阅KN King:C编程现代方法

根据语言定义,字符串文字必须以这样的方式存储,即它们的生命周期在程序的生命周期中延伸,并且它们在整个程序中是可见的。

究竟这意味着字符串存储的位置取决于实现 ; 语言定义并不强制将字符串文字存储在只读内存中,并非所有实现都这样做。 它只表示尝试修改字符串文字的内容会导致未定义的行为,这意味着实现可以随意执行任何操作。