为什么这个代码的行为在C中未定义?

问题描述:

我已经给出了这段代码,我不太确定它的行为为何未定义。我的猜测是它与两个字符串的内存位置以及if条件中的位置比较有关。为什么这个代码的行为在C中未定义?

int main(void) { 
    char *str1 = "xyz"; 
    char *str2 = "xyz"; 

    if (str1 == str2) { 
    printf("Same!\n"); 
    } else { 
    printf("Not Same!\n"); 
    } 
    return 0; 
} 
+5

它不是未定义的。 6.4.5节定义了这种行为。 (如果它没有定义,输出结果可能是“我喜欢馅饼!”,这只是未指定的。) – 2013-04-23 06:18:24

它未指定(未未定义,有一个微妙的区别),以相同的字符串常量是否被折叠以占据相同的存储器。

C++11, 6.4.5 String literals /6状态:

它是未指定的这些阵列是否是不同的条件是它们的元件具有 适当的值。如果程序试图修改这样一个数组,行为是 未定义。

两个str1str2是包含4个字符{ 'x', 'y', 'z', '\0'}指针的存储器的块和它们根据定义,不可修改的。

这意味着如果需要的话,编译器可以*地将这两个变量设置为指向相同的内存块,以提高效率。

因此str1str2(我说的是指针,显然内容指针后面是相同的)可以是相同的或没有。

+0

我可以在哪里阅读更多关于它的内容? – 2013-04-23 06:18:21

+0

我进一步说,许多编译器已经将常用文字合并为强制设置,可以强制关闭,或者由编译器/链接器自行决定。 – WhozCraig 2013-04-23 06:21:12

+0

这与询问编译器是否从不同位置获取两个3,或者它是否从类似于int i = 3的代码中的相同位置获取3都是一样的。 int j = 3;'。除了因为你有一个指向初始化值的指针,你可以告诉它它做了什么。编译器可以*地做到这一点。 – 2013-04-23 06:22:17

C不支持字符串比较操作,以便在使用==操作符,它实际上比较字符串的地址和比较字符串,因为它没有定义“XYZ”字符串常量,将在只读存储器相同的内存地址。它依赖于编译器和机器。

+0

什么?那么你的意思是存储在不同位置的两个相似的字符串将不相等? – 2013-04-23 06:21:45

+3

@SheerFish:两个不同的地点将是不平等的。他在比较地址。 – 2013-04-23 06:24:12

+0

@SheerFish它的编译器是否将相同的字符串存储在相同的内存中或不同,并且==运算符比较比较字符串的基本地址,因为这两个ptr都将指向只读字符串的起始地址。 – 2013-04-23 06:24:52

也许它是未定义的,因为它取决于编译器如何优化字符串。如果不知道使用什么选项的编译器,结果就不能一概而定。

“XYZ”是一个字符串字面它放在为“只读”部分被映射到进程空间为只读(这就是为什么你不能改变它)。

因此str1str2指向相同的地址。这是执行printf("Same!\n");的原因。

这取决于平台。请参考String literals: Where do they go?