C++ string literal equality check?

拜拜、爱过 提交于 2020-01-02 06:09:20

问题


== 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!