Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Comparison of String Literals

I'm a c++ newbie (just oldschool c). My son asked for help with this and I'm unable to explain it. If he had asked me "how do I compare strings" I would have told him to use strcmp(), but that isn't what is confusing me. Here is what he asked:

int main() 
{ 
  cout << ("A"< "Z");
}

will print 1

int main() 
{ 
  cout << ("Z"< "A");
}

will also print 1, but

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}

will then print 10. Individually both cout statements print 1, but executed in a row I get a different answer?

like image 929
simusid Avatar asked Dec 12 '14 18:12

simusid


People also ask

Can you compare string literals in C?

In C, you can compare single characters (chars) by using the comparion operator ==, however, this method is not valid for comparing arrays of chars, or strings. Instead, you must use a function that compares each of the chars within the arrays in turn.

How do you compare string literals?

To compare string literals, still use the equality and relational operators, but for objects of the string class, and not for const char*s. Using the operators for const char*s compares the pointers, and not the string literals.

Can I use == to compare strings in C?

In C, string values (including string literals) are represented as arrays of char followed by a 0 terminator, and you cannot use the == operator to compare array contents; the language simply doesn't define the operation.

How do I compare strings in C?

We compare the strings by using the strcmp() function, i.e., strcmp(str1,str2). This function will compare both the strings str1 and str2. If the function returns 0 value means that both the strings are same, otherwise the strings are not equal.


4 Answers

You are comparing memory addresses. Apparently your compiler places the string literals in memory in the order it encounters them, so the first is "lesser" than the second.

Since in the first snippet it sees "A" first and "Z" second, "A" is lesser. Since it sees "Z" first in the second, "Z" is lesser. In the last snippet, it already has literals "A" and "Z" placed when the second command rolls around.

like image 139
Wintermute Avatar answered Oct 16 '22 22:10

Wintermute


String literals have static storage duration. In all these comparisons there are compared addresses of memory allocated by the compiler for string literals. It seems that the first string literal that is encountered by the compiler is stored in memory with a lower address compared with the next encountered string literal.

Thus in this program

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}

string literal "Z" was alllocated with a lower address than string literal "A" because it was found first by the compiler.

Take into account that comparison

  cout << ("A"< "A");

can give different results depending on the options of the compiler because the compiler may either allocate two extents of memory for the string literals or use only one copy of the string literals that are the same.

From the C++ Standard (2.14.5 String literals)

12 Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation defined. The effect of attempting to modify a string literal is undefined.

The same is valid for C.

like image 34
Vlad from Moscow Avatar answered Oct 16 '22 21:10

Vlad from Moscow


In the statement:

cout << ("A"< "Z");

You have created 2 string literals: "A" and "Z". These are of type const char * which is a pointer to a null terminated array of characters. The comparison here is comparing the pointers and not the values that they point to. It's this comparing of memory addresses here which is what gives you the compiler warning. The result of the comparison is going to be determined by where the compiler allocated the memory to which is going to be somewhat arbitrary from compiler to compiler. In this case it looks like the first literal found is getting assigned the first memory address by your compiler.

Just like in C to compare these string literals properly you need to use strcmp which will do a value comparison.

However when you do something the more idiomatic c++ way by doing:

cout << (std::string("A") < std::string("Z"));

Then you get the proper comparison of the values as that comparison operator is defined for std::string.

like image 15
shuttle87 Avatar answered Oct 16 '22 23:10

shuttle87


If you want to compare actual C++ strings, you need to declare C++ strings:

int main() 
{
  const std::string a("A");
  const std::string z("Z");

  cout << (z < a) << endl; // false
  cout << (a < z) << endl; // true
}
like image 7
tadman Avatar answered Oct 16 '22 23:10

tadman