5

所以我做了以下测试:

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

现在的问题是:

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

2)为什么不a==c呢?编译器不应该能够看到它们指的是同一个字符串吗?

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

我不想为此问 3 个不同的问题,因为它们似乎有点相关,抱歉。

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

4

7 回答 7

18

是否保证a==b?

不可以。但是 §2.14.5/12 允许这样做:

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

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

为什么不 a==c?编译器不应该能够看到它们指的是同一个字符串吗?

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

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

是的。

于 2012-05-24T17:24:41.090 回答
6

1 - 绝对不是。a 可能 == b 但如果编译器选择共享相同的静态字符串。

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

3 - 是的。

除了 C++ 编译器应该拒绝对非 const char* 的赋值之外,这里的 C 和 C++ 之间的行为没有什么不同。

于 2012-05-24T17:24:05.707 回答
4

1)是否保证a==b?

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

2)为什么不 a==c?编译器不应该能够看到它们指的是同一个字符串吗?

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

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

就在这里。

于 2012-05-24T17:25:17.020 回答
3

首先请注意,这应该是 const char* ,因为这就是字符串文字衰减的原因。

  1. 两者都创建用 't' 'e' 's' 't' 初始化的数组,后跟 '\0' (长度 = 5)。比较相等性只会告诉您它们是否都以相同的指针开头,而不是它们是否具有相同的内容(尽管从逻辑上讲,这两个想法是相互遵循的)。
  2. A 不等于 C,因为适用相同的规则,a = 't' 'e' 's' 't' '\0' 和 b = 't' 'e' 's' 't' '\0' '\0'
  3. 是的,编译器总是这样做,如果你正在制作这样的字符串,你不应该明确地这样做。但是,如果您创建了一个数组并手动填充它,则需要确保添加 \0。

请注意,对于我的#3, const char[] = "Hello World" 最后也会自动获得 \0,我指的是手动填充数组,而不是让编译器解决它。

于 2012-05-24T17:28:21.663 回答
2

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

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

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

于 2012-05-24T17:24:51.663 回答
0

如果您进行的指针比较比 a != b、b != c 和 c != a。除非编译器足够聪明,可以注意到您的前两个字符串是相同的。

如果您执行 strcmp(str, str) 那么您的所有字符串都将作为匹配项返回。

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

于 2012-05-24T17:25:32.973 回答
0

正如在其他答案中多次说过的那样,您正在比较指针。但是,我要补充一点,这strcmp(b,c)应该是正确的,因为它在第一个\0.

于 2012-05-24T17:33:25.010 回答