-2

这有效:

int main()
{      
    char *t = "Hello";
    t = "World";
    printf("%s", t);
}

但这会产生分段错误:

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

为什么?

4

7 回答 7

4

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

在第一个示例中,您没有将“Hello”字符串更改为“World”字符串。您正在重新分配t,使其指向“World”而不是“Hello”。“Hello”字符串仍然在只读存储器中徘徊,未受影响。

这是初始状态:

t -> "Hello"
     "World"

这是第二种状态:

     "Hello"
t -> "World"

在第二个示例中,您试图覆盖“Hello”字符串。这是无法做到的。

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

于 2013-08-22T19:10:53.010 回答
3

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

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

编码

char *test = "Hello";

意味着编译器+链接器将一串字节“Hello\0”放在只读部分中,并将test点指向其中的第一个字符。任何通过此指针写入的尝试都将受到操作系统的严厉惩罚。

另一方面

char test[] = "Hello";

声明一个 6 个字符的数组,初始值为 ( { 'H', 'e', 'l', 'l', 'o', '\0' })。

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

于 2013-08-22T19:08:17.127 回答
3

第一个将 的值t从 的地址更改"Hello"为 的地址"World"。第二个尝试覆盖数据"Hello"本身。

于 2013-08-22T19:10:34.130 回答
2

赋值t = "World"只改变指针,而strcpy改变 t 指向的内存。字符串文字可能存在于只读段中。

于 2013-08-22T19:12:02.463 回答
2

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

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

于 2013-08-22T19:12:14.970 回答
2

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

分配和复制是有区别的。

第一个示例,您尝试将另一个字符串的地址分配给t.

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

使用 char t[] = "Hello"。这里 t 可以被覆盖

更多解释在这里

于 2013-08-22T19:11:40.400 回答
1

“Hello”是一个字符串常量。根据constant的定义,它并不意味着要写在上面。

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

于 2013-08-22T19:10:37.347 回答