包含'\ 0'的字符串文字 - 为什么它们不相同?

时间:2012-05-24 17:22:13

标签: c++ string

所以我做了以下测试:

char* a = "test";
char* b = "test";
char* c = "test\0";

现在的问题是:

1)是否保证a==b我知道我正在比较地址。这并不是要比较字符串,而是将相同的字符串文字存储在单个内存位置

2)为什么不a==c?编译器是否应该能够看到它们引用相同的字符串?

3)在\0的末尾是否附加了额外的c,即使它已包含一个?

我不想为此提出3个不同的问题,因为它们似乎有点相关,对不起'回合那个。

注意:标签是正确的,我对C ++感兴趣。 (但请指明C的行为是否不同

7 个答案:

答案 0 :(得分:18)

  

是否保证a == b?

没有。但是§2.14.5/ 12允许它:

  

是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。尝试修改字符串文字的效果未定义。

正如您从最后一句使用char*而不是char const*所看到的那样是一个麻烦的方法(您的编译器应该拒绝它;确保您启用了警告并选择了高一致性级别)。

  

为什么不= = c?编译器是否应该能够看到它们引用相同的字符串?

不,他们不需要引用相同的字符数组。一个有五个元素,另外六个。实现可以将两者存储在重叠存储中,但这不是必需的。

  

是否在c的末尾附加了一个额外的\ 0,即使它已经包含一个?

答案 1 :(得分:6)

1 - 绝对没有。如果编译器选择共享相同的静态字符串,则可能== b。

2 - 因为它们不是指同一个字符串

3 - 是的。

C和C ++之间的行为没有区别,除了C ++编译器应该拒绝赋予非const char *。

答案 2 :(得分:4)

  

1)是否保证a == b?

不是。请注意,您正在比较地址,它们可能指向不同的位置。大多数智能编译器会折叠这个重复的文字常量,因此指针可以比较相等,但标准不能保证它。

  

2)为什么a == c?编译器是否应该能够看到它们引用相同的字符串?

您正在尝试比较指针,它们指向不同的内存位置。即使您在比较这些指针的内容,它们仍然是不相等的(参见下一个问题)。

  

3)在c的末尾附加了一个额外的\ 0,即使它已经包含一个?

是的,有。

答案 3 :(得分:3)

首先请注意,这应该是const char *,因为这是字符串文字衰变的内容。

  1. 两个创建的数组都使用't''e'''t'初始化,后跟'\ 0'(长度= 5)。比较相等只会告诉你它们是否都以相同的指针开头,而不是它们具有相同的内容(尽管从逻辑上讲,这两个想法是相互依存的)。
  2. A不等于C,因为同样的规则适用,a ='t''e''t''\ 0'和b ='t''e'''t'' \ 0''\ 0'
  3. 是的,编译器总是这样做,如果你正在制作这样的字符串,你不应该明确地做。但是,如果您创建了一个数组并手动填充它,则需要确保添加\ 0。
  4. 请注意,对于我的#3,const char [] =“Hello World”也会在结尾处自动获得\ 0,我正在努力手动填充数组,而不是让编译器完成它。

答案 4 :(得分:2)

这里的问题是你在混合指针和文本等价的概念。

当您说a == ba == c时,您询问所涉及的指针是否指向同一物理地址。测试与指针的文本内容无关。

要获得文本等效,您应该使用strcmp

答案 5 :(得分:0)

如果您正在进行指针比较而不是!= b,b!= c和c!= a。除非编译器足够智能,否则会注意到前两个字符串是相同的。

如果你执行strcmp(str,str),那么你的所有字符串都会以匹配的形式返回。

我不确定编译器是否会向c添加额外的空终止,但我猜它会。

答案 6 :(得分:0)

正如在其他答案中已经说过几次,你正在比较指针。但是,我想补充说strcmp(b,c)应该是真的,因为它会在第一个\0停止检查。