包含'\ 0'的字符串文字 - 为什么它们不一样?
所以我做了如下试验:包含' 0'的字符串文字 - 为什么它们不一样?
char* a = "test";
char* b = "test";
char* c = "test\0";
而现在的问题:
1)能够保证所有的a==b
? 我知道我在比较地址。这并不意味着要比较字符串,但相同的字符串文字是否存储在单个内存位置
2)为什么不是a==c
?编译器不应该看到它们指的是相同的字符串吗?
3)c
的末尾是否附加了\0
,即使它已经包含了一个?
我不想问这3个不同的问题,因为他们似乎有点相关,对不起'布特那。
注:标签是正确的,我对C++感兴趣。 (虽然请说明C的行为是否不同)
是否保证a == b?
号但它是由§2.14.5/ 12允许:
是否所有字符串文字是不同的(即,被存储在非重叠的对象)是实现定义。试图修改字符串文字的效果是未定义的。
而且,你可以使用char*
代替char const*
最后一句看到的是一个麻烦的食谱(和你的编译器应该拒绝它,请确保您有打开了警告,并选择高一致性水平)。
为什么不是a == c?编译器不应该看到它们指的是相同的字符串吗?
不,他们不需要指的是相同的字符数组。一个有五个要素,另外六个要素。一个实现可以将这两个存储在重叠存储中,但这不是必需的。
在c的末尾添加了一个\ 0,即使它已经包含了一个?
是的。
1 - 绝对不是。如果编译器选择共享相同的静态字符串,则可能会出现一个== == b。
2 - 因为它们不是指相同的字符串
3 - 是的。
这里的C和C++的行为没有什么不同,只是C++编译器应该拒绝赋值给非const char *。
字符串文字转换为char *转换已被弃用,但在C++中不被禁止。 –
@james它在C++中被禁止11 –
@ JohannesSchaub-litb:没办法!这是我一整天听到的最好的消息。 g ++ 4.7,clang 3.1和VC11都接受这种转换,但我期待他们不会这样做:-) –
1)能够保证所有的A == B'
不是。请注意,您正在比较地址,他们可能指向不同的位置。大多数智能编译器会折叠这个重复的文字常量,因此这些指针可能会相等,但又不会被标准保证。
2)为什么不a == c?编译器不应该看到它们指的是相同的字符串吗?
您试图比较指针,它们指向不同的内存位置。即使你在比较这些指针的内容,它们仍然是不相等的(见下一个问题)。
3)在c的末尾是否附加了一个\ 0,即使它已经包含了一个?
是的,有。
我知道我在比较地址,请问这个问题。要清除这个问题 - 相同的字符串文字位于相同的内存中吗? – AMCoder
我猜'a'和'c'的指针可以相等。一个程序不能在不调用UB的情况下区分它们。 –
@R。马丁尼费尔南德斯:这是一个好点,我相信你是对的。 –
如果你正在做指针比较比!= b,b!= c,并且c!= a。除非编译器足够聪明才能注意到你的前两个字符串是相同的。
如果你做了一个strcmp(str,str),那么你所有的字符串都会作为匹配返回。
我不确定编译器是否会向c添加一个额外的空终止符,但我猜测它会。
首先注意,这应该是const char *,因为这是字符串文字衰减到的。
- 两者都创建用't''e''s''t'用'\ 0'(长度= 5)覆盖的初始化数组。比较平等只会告诉你他们是否都以相同的指针开始,而不是如果他们有相同的内容(尽管在逻辑上,这两个想法相互依存)。
- A不等于C,因为相同的规则适用,a ='t''e''s''t''\ 0'和b ='t''e''s''t'' \ 0''\ 0'
- 是的,编译器总是这样做,你不应该在做这样的字符串时明确地做。但是,如果您创建了一个数组并手动填充它,则需要确保添加\ 0。
请注意,对于我的#3,const char [] =“Hello World”也会在最后自动获得\ 0,我正在重新手动填充数组,而不是让编译器解决它。
我不认为'a'和'c'保证不相等。该标准允许实现将文字存储在重叠存储中,并且程序无法在不调用UB的情况下区分这些差异。 –
我确实同意你的检查,这是一个我没有听说过的点。我的观点仍然是,编译器肯定会在情况2中放置两个空终止符,尽管这会使操作不平等,即使读取字符串和检查它们的指针也是相等的。另外,如果您记录了为c创建的字符串的长度,则可以安全地读取strlen()的过去1,并且不能为a(除非它们与您所说的位置相同,但是您不会)不能保证)。 –
*即使编译器将它们存储在相同的位置*,“a [5]”(它尝试读取与c [5]'相同位置的值)会调用未定义的行为,因为“a”指向一个大小为5的数组。没关系的是恰好有另一个数组放在同一个地方。 –
正如其他答案中所说的几次,你在比较指针。但是,我会补充说strcmp(b,c)
应该是真的,因为它在第一个\0
停止检查。
应该是'char const * a = ...'。 –
a和b具有相同的值,但这并不一定意味着它们是_same_字符串。 –
@HunterMcMillen - 其实这就是它的意思。 –