为什么这两个指针相等?寻求澄清.

sim*_*ont 5 c

我有一个简单的程序:

int main() {
    char *c = "message";
    char *z = "message";

    if ( c == z )
        printf("Equal!\n");
    else
        printf("Not equal!\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这个打印Equal!,即使在关闭优化的情况下进行编译(-O0).这将表明,这两个cz指向相同的内存区域,并因此在第一突变z(例如,改变z[0]a)将是昂贵的(需要复制和写入).

我对正在发生的事情的理解是我没有声明一个类型数组char,而是创建一个指向a的第一个字符的指针string literal.因此,c并且z都存储在数据段中,而不是存储在堆栈中(并且因为它们都指向相同的字符串文字,所以c == z是真的).

这与写作不同:

char c[] = "message";
char z[] = "message";

if ( c == z ) printf("Equal\n");
else printf("Not equal!\n");
Run Code Online (Sandbox Code Playgroud)

其打印Not equal!,因为c并且z都存储在存储器的可变部分(即,堆栈)中,并且被单独存储,使得一个的突变不影响另一个.

我的问题是,我看到(c == zas true)定义的行为是什么行为?char *c尽管没有被声明为存储在数据段中,但似乎令人惊讶const.

当我尝试变异char *z定义时的行为?为什么,如果char *c = "message"放入数据段并因此是只读的,我是否得到bus error而不是编译器错误?例如,如果我这样做:

char *c = "message";
c[0] = 'a';
Run Code Online (Sandbox Code Playgroud)

我明白了:

zsh: bus error  ./a.out
Run Code Online (Sandbox Code Playgroud)

虽然它快乐地编译.

任何进一步澄清这里发生的事情以及为什么会受到赞赏.

Ela*_*zar 7

"第一个突变z(例如,更改z[0]a)将是昂贵的(需要复制和写入)."

不贵啊"; 尝试未定义.字符串文字是常量.


Bil*_*nch 2

C 2011 标准。第 6.4.5 节。字符串文字。第 7 段

未指定这些数组 [字符串文字] 是否不同,前提是它们的元素具有适当的值。如果程序尝试修改这样的数组,则行为是未定义的。

这意味着如果两个字符串文字具有相同的值,则允许编译器将它们指向内存中的相同位置或不同位置,但这只是编译器可以做出的选择。