strcpy()的分段错误

strcpy()的分段错误,c,strcpy,C,Strcpy,这项工作: int main() { char *t = "Hello"; t = "World"; printf("%s", t); } 但这给了细分错误: int main() { char *t = "Hello"; strcpy(t, "World"); // the only difference printf("%s", t); } 为什么?在第一个示例中,指针t指向字符串常量“Hello”,然后立即指向字符

这项工作:

int main()
{      
    char *t = "Hello";
    t = "World";
    printf("%s", t);
}
但这给了细分错误:

int main()
{   
    char *t = "Hello";   
    strcpy(t, "World"); // the only difference
    printf("%s", t);
}

为什么?

在第一个示例中,指针
t
指向字符串常量
“Hello”
,然后立即指向字符串常量
“World”
;然后打印后一个值

第二个示例中的代码因segfault崩溃,因为字符串常量不可写。(strcpy尝试修改保存文本的内存
“Hello”
)。GCC将字符串常量放入只读部分,除非使用
-fwriteable strings
编译

代码

char *test = "Hello";
表示编译器+链接器在只读节中放置一个字节字符串“Hello\0”,并且
test
指向其中的第一个字符。任何试图写入此指针的行为都将受到操作系统的严厉惩罚

另一方面

char test[] = "Hello";
声明一个由6个字符组成的数组,初始值为(
{'H','e','l','l','o','\0'}


一些旧程序假设字符串常量是可写的;因此,要求GCC支持使用
-fwriteable strings
命令行开关编译这些程序。

首先将
t
的值更改为从
“Hello”
的地址指向
“World”
的地址。第二个尝试覆盖数据本身。

“Hello”是一个字符串常量。根据常量的定义,它不是用来写的


在第一个示例中,“t”是一个指针,它可以指向(分配)字符串常量。

您明确定义的字符串(例如,
“Hello”
)通常放置在只读内存区域中。这些字符串不能更改

在第一个示例中,您没有将“Hello”字符串更改为“World”字符串。您正在重新分配
t
,以便它指向“World”而不是“Hello”。“Hello”字符串仍然挂在只读内存中,未被触动

以下是初始状态:

t -> "Hello"
     "World"
这是第二种状态:

     "Hello"
t -> "World"
在第二个示例中,您试图覆盖“Hello”字符串。这是不可能做到的

您应该将声明从
char*t
更改为
const char*t
。我认为可以将GCC配置为强制执行此操作。

char*t=“Hello”
t
中,在只读位置分配“Hello”。因此,写入只读位置会导致分段错误

分配和复制之间有区别

第一个示例是您试图将另一个字符串的地址分配给
t

在第二个示例中,您试图写入只读位置

使用char
t[]=“Hello”
。在这里,t可以被覆盖


更多说明赋值
t=“World”
仅更改指针,而
strcpy
更改t指向的内存。字符串文字可能位于只读段中。

char*t
是指针。在第一个示例中,您只是将指针从一个字符串文本分配到另一个字符串文本:首先
t
指向
“Hello”
,然后指向
“World”
。这是完全合法的


但是,字符串文字本身就是文字——它们不能更改。通常,它们位于内存的只读部分。在第二个示例中,您试图更改分配给字符串literal
“Hello”
的内存中的内容,方法是用
“World”
覆盖它。这是非法的,你会得到一个分割错误

那么第一个程序(t=“world”)@user2076561呢?因为
p
是一个指针,它与字符串文字不同。@user2076561在第一个程序中,您不是在写
“world”
以前的
“Hello”
,而是将指针指向其他地方。
char*t=“Hello”;“是一个指针,指向一个
string literal
。你可以自由地将它分配给另一个
string literal`但不能
将一些数据(例如字符串)存储在内存中。这就是答案的本质,我认为下面的答案中有人投了反对票——如果是你——请去把它投回去。”。