Why does the `equal` works for const char* in C++?

algorithm, c++, char, stl, string

Solution

What probably happens here is that the compiler/linker merges the four string literals of which two are identical into two literals. Therefore, both `"nima"` and both `"123"` have the same address.

You store the addresses in a vector and compare them (`operator==` on an address). Since the addresses are the same, the comparison is equal.

Note that this is accidential. It only "works" because of two reasons:

- The strings are literals (that is, not some strings read from e.g. `stdin`).

- A compiler is allowed, but not required to merge identical literals (whether or not this happens is implementation-defined).

This can lead to two situations in which you get a funny surprise (not so funny if you must find out why it suddenly doesn't work when it "worked" all the time), either when you use a different compiler or even the same compiler with different optimization settings, or when you assign non-literal strings.

Problem

The codes are like this, it outputs `1`: ``` int main(int argc, char *argv[]) { vector <const char*> vec = {"nima","123"}; vector <const char*> vec2 = {"nima","123"}; auto result = equal(vec.cbegin(), vec.cend(), vec2.cbegin()); cout << result << endl; return 0; } ``` I knew that I can test whether two c-style string is equal only by using `strcmp` (because `char*` is not an object as I understood). But here `equal` is a function from `<algorithm>`. Does it overload the `==` operator so that it can test the equality of two `char*`? @Damon says that they're equal as the merges the same string literal into same address, as I understood. However, when I tried `char*` with different addresses, it still gives me the same result: ``` int main(int argc, char *argv[]) { char* k = "123"; char* b = "123"; vector <const char*> vec = {"nima"}; vector <const char*> vec2 = {"nima"}; cout << &k << endl; cout << &b << endl; vec.push_back(k); vec2.push_back(b); auto result = equal(vec.cbegin(), vec.cend(), vec2.cbegin()); cout << result << endl; return 0; } ``` The result is: ``` 0x7fff5f73b370 0x7fff5f73b368 1 ```

Original source