3

我有一个问题,我看到两个指针的地址与这里的问题相同(两个指针的地址相同),蓝月亮也回答了。这让我产生了更多的疑问。由于两个指针具有相同的地址,我想更改其中一个指针的值,因此其他指针中的预期值也会更改(因为它们具有相同的地址)。但它给出了分段错误。我在下面的代码中显示它。

#include<stdio.h>
#include<string.h>

int main()
{
    char * p = "abc";
    char * p1 = "abc";
    printf("%d\n %d\n", (void *)p, (void *)p1);
    printf("%s\n %s\n", p, p1);
    *p = 'b';
    printf("%d\n %d\n", p, p1);
    printf("%s\n %s\n", p, p1);
}
4

4 回答 4

6

C90, 6.1.4

如果程序尝试修改任一形式的字符串文字,则行为未定义。

在您的情况下,这种未定义的行为对您有利,因此您会遇到 Seg 错误。除了使用此打印指针%d不是一个好习惯外,您应该使用%p.

现在从您给定的 Blue Moon 链接答案

您应该始终将pandp1视为两个不同的指针(即使它们具有相同的内容),因为它们可能指向或不指向相同的地址。您不应该依赖编译器优化。

于 2013-09-30T09:36:49.490 回答
3
char * p = "abc";
*p = 'b';

调用未定义的行为,因为您正在尝试修改只读内存。您无法更改此常量字符串文字所在的内存。

使用此文字来初始化数组:

char myStr[] = "abc";
char *p = &myStr[0];
char *p2 = &myStr[0];  // <-- p and p2 point to the same address now
*p = 'b';
printf("%s\n", p2);    // <-- prints bbc
于 2013-09-30T09:36:01.680 回答
3

编码

char * p = "abc";

可以将字符串文字放在只读内存中,因此从技术上讲,您不应该修改它。这可能会给您带来段错误。这也是为什么两个指针可能相同的原因......编译器足够聪明,可以识别它们都使用相同的字符串文字,因此只存储一个文字实例。

如果您将其声明为

char p[] = "abc"

然后这将在堆栈上创建一个由 4 个字符(3 个和 1 个空终止符)组成的可读/可写数组,然后您可以对其进行修改,但是......

char p[] = "abc";
char p1[] = "abc";

您会发现p1 != p两者都是在堆栈上使用单独的存储创建的(我假设它们不是全局变量)

此外,当printf用于打印指针值时,我认为最好使用%p.

于 2013-09-30T09:38:45.967 回答
2

字符串文字存储在只读内存段中,因此尝试修改它会导致分段错误。这是因为字符串文字数据可以被许多指针引用,并且修改它会修改其他常量字符串。

于 2013-09-30T09:35:44.920 回答