问题
==
is not how we compare two arrays, since that would only compare the addresses:
#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;
}
This code even gives me a warning:
Array comparison always evaluates to false
But when I tried this:
if ("aaa" == "aaa")
It seemed to be working fine. Still gives me a warning, but the warning is:
Condition is always true
At first, I thought it was some kind of caching thing, so I tried a rather unusual string literal:
if ("whuiwhqohqweihqweohi" == "whuiwhqohqweihqweohi")
Still works fine both on MSVC and g++. Is that an implementation dependent behavior? I understand that comparing variables which are known at compile-time is not very useful, but my question is just "how come this is the case?".
Additionally, using auto
seems to be also working:
#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;
}
This code produces the correct output. What is the type of a
and b
here?
Please do not answer "Use std::string". It's irrelevant to my question
回答1:
You have to be very careful here, as some of the cases you're looking at aren't quite equivalent to others.
In your first example:
char a[] = "aaa";
char b[] = "aaa";
if (a == b)
You're creating two arrays of char, each initialized from an string literal. You're then attempting to compare those arrays to each other. In most cases (including this one) the name of an array evaluates to the address of the first element in that array. So you're really comparing the addresses of the two arrays. Those can't be the same, so the comparison is guaranteed to yield false
.
In your second example: if ("aaa" == "aaa")
, you're comparing the string literals themselves, rather than arrays initialized from the string literals.
The result of this is not guaranteed by the standard. The standard allows (but does not require) that identical string literals be merged together. Again, however, what you're really comparing isn't the contents of the literals--it's the addresses at which they're stored. If the compiler merges the string literals so they're at the same address, this will yield true
. If it keeps them separate, it'll yield false
.
In your auto
case:
auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";
You have pretty much the same situation--a
and b
both end up as pointers to char, holding the addresses of the string literals. If the compiler merges those literals, they'll both point to the same address so they'll compare equal. If the compiler doesn't merge them together, each will have its own address, and they'll compare as not equal.
The big point here is that none of these is comparing the contents of the strings at all, only the addresses at which they're stored. The content counts only to the degree that two string literals can only be merged if they have (or at least end with) the same content.
As far as "at least end with" goes, I'm referring to the fact that a compiler if you had something like: "wing"
in one place and "swing"
in another, the compiler is free to merge the two, so with code something like:
auto a = "wing";
auto b = "swing";
...the compiler could store swing
in one place, and initialize a
to point to the second character of that stored literal.
回答2:
For
char a[] = "aaa";
char b[] = "aaa";
You compare address of local arrays a
and b
, so cannot have same address.
For
if ("aaa" == "aaa")
You compare 2 static char pointers which might be identical or not.
From string_literal
The compiler is allowed, but not required, to combine storage for equal or overlapping string literals. That means that identical string literals may or may not compare equal when compared by pointer.
bool b = "bar" == 3+"foobar" // could be true or false, implementation-defined
In the same case:
auto a = "whuiwhqohqweihqweohi";
auto b = "whuiwhqohqweihqweohi";
auto
is const char*
.
回答3:
The two literal strings are constant and the compiler is likely to replace the two instances you have in your code with one instance and then replace it with true.
The auto
a
and b
are char const*
.
来源:https://stackoverflow.com/questions/53965165/c-string-literal-equality-check