==
不是我们比较两个数组的方式,因为那样只会比较地址:
#include <iostream>
int main()
{
char a[] = "aaa";
char b[] = "aaa";
if (a == b)
std::cout << "Yes" << std::endl;
else
std::cout << "No" << std::endl;
return 0;
}
此代码甚至给我一个警告:
数组比较的总结果为false
但是当我尝试这样做时:
if ("aaa" == "aaa")
似乎工作正常。仍然给我一个警告,但警告是:
条件永远是真的
起初,我认为这是某种缓存内容,所以我尝试了一种非常不寻常的字符串文字:
if ("whuiwhqohqweihqweohi" == "whuiwhqohqweihqweohi")
在MSVC和g ++上仍然可以正常工作。那是依赖实现的行为吗?我知道比较在编译时已知的变量不是很有用,但是我的问题是“情况如何?”。
另外,使用auto
似乎也可以:
#include <iostream>
int main()
{
auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";
if (a == b) {
std::cout << "Yes" << std::endl;
}
else {
std::cout << "No" << std::endl;
}
return 0;
}
此代码产生正确的输出。这里的a
和b
是什么类型?
请不要回答“使用std :: string”。这和我的问题无关
答案 0 :(得分:7)
在这里您必须非常小心,因为您正在寻找的某些情况与其他情况并不完全相同。
在您的第一个示例中:
char a[] = "aaa";
char b[] = "aaa";
if (a == b)
您正在创建两个char的数组,每个数组都是从字符串文字初始化的。然后,您尝试将这些数组相互比较。在大多数情况下(包括此情况),数组的名称将求值为该数组中第一个元素的地址。因此,您实际上是在比较两个阵列的地址。两者不能相同,因此可以保证比较产生false
。
在第二个示例if ("aaa" == "aaa")
中,您正在比较字符串文字自身,而不是从字符串文字中初始化的数组。
标准不保证其结果。该标准允许(但不要求)将相同的字符串文字合并在一起。同样,您真正要比较的不是文字的内容,而是它们存储的地址。如果编译器合并了字符串文字,因此它们位于相同的地址,则将产生true
。如果将它们分开,则会产生false
。
在您的auto
情况下:
auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";
您几乎有相同的情况-a
和b
都以char的指针结尾,并持有字符串文字的地址。如果编译器合并了这些文字,它们都将指向相同的地址,因此它们将比较相等。如果编译器没有将它们合并在一起,则每个都有自己的地址,并且它们将比较不相等。
这里最重要的一点是,这些都不是完全比较字符串的内容,而只是比较存储它们的地址。内容仅在两个字符串文字具有相同内容(或至少以相同结尾)的情况下才能合并。
至于“至少以...结尾”,我指的是这样一个事实:如果您有一个地方"wing"
,而另一个地方"swing"
,则编译器是可以自由合并两者,因此使用类似以下代码的代码:
auto a = "wing";
auto b = "swing";
...编译器可以将swing
存储在一个位置,并初始化a
指向存储的文字的第二个字符。
答案 1 :(得分:6)
对于
char a[] = "aaa";
char b[] = "aaa";
您比较本地阵列的地址 a
和b
,因此不能有相同的地址。
对于
if ("aaa" == "aaa")
您比较2个可能相同或不同的静态char指针。
允许(但不是必需)编译器组合存储以相等或重叠的字符串文字。这意味着,当通过指针进行比较时,相同的字符串文字可能会比较相等,也可能不会相等。
bool b = "bar" == 3+"foobar" // could be true or false, implementation-defined
在相同情况下:
auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";
auto
是const char*
。
答案 2 :(得分:3)
这两个文字字符串是常量,编译器可能会用一个实例替换您在代码中拥有的两个实例,然后将其替换为true。
auto
a
和b
是char const*
。