21
int main (int argc, **argv)
{
       if (argv[1] == "-hello")
            printf("True\n");
       else
            printf("False\n");
}
# ./myProg -hello
False

Why? I realize strcmp(argv[1], "-hello") == 0 returns true... but why can't I use the equality operator to compare two C strings?

Rodrigo de Azevedo
  • 1,097
  • 9
  • 17

9 Answers9

23

Because argv[1] (for instance) is actually a pointer to the string. So all you're doing is comparing pointers.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
17

You can't compare strings in C with ==, because the C compiler does not really have a clue about strings beyond a string-literal.

The compiler sees a comparison with a char* on either side, so it does a pointer comparison (which compares the addresses stored in the pointers)

Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
15

In C because, in most contexts, an array "decays into a pointer to its first element".

So, when you have the array "foobar" and use it in most contexts, it decays into a pointer:

if (name == "foobar") /* ... */; /* comparing name with a pointer */

What you want it to compare the contents of the array with something. You can do that manually

if ('p' == *("foobar")) /* ... */; /* false: 'p' != 'f' */
if ('m' == *("foobar"+1)) /* ... */; /* false: 'm' != 'o' */
if ('g' == *("foobar"+2)) /* ... */; /* false: 'g' != 'o' */

or automatically

if (strcmp(name, "foobar")) /* name is not "foobar" */;
pmg
  • 106,608
  • 13
  • 126
  • 198
  • 1
    `if(strcmp(name, "foobar"))` will evaluate to false if strings are equivalent because it returns 0 in that case. `if (strcmp(name, "foobar") == 0)` would be better – Overdrivr Jan 13 '16 at 17:46
  • Thanks for the heads up @Overdrivr. Comment added to the code to make it clear. – pmg Jan 14 '16 at 10:15
6

Because there is no such thing as a C string.

In C, a string is usually an array of char, or a pointer to char (which is nearly the same). Comparing a pointer/array to a const array won't give the expected results.

UPDATE: what I meant by 'no C string' is, there is no string in C. What's usually referred to as a 'C string' is language independent (as 'Pascal string' is), it's the representation of strings as a null-terminated linear array of characters.

jv42
  • 8,521
  • 5
  • 40
  • 64
  • 4
    There is definitely a thing called a [C string](http://en.wikipedia.org/wiki/C_string). I don't know exactly what you mean. Perhaps that "There is no C string-type in the C language"? – Magnus Hoff Oct 14 '10 at 14:05
  • That's just abusing the term. What's described there is a null-terminated string, as opposed to a 'Pascal String', which gives the size as the first byte. – jv42 Oct 14 '10 at 14:17
  • Now, the C programming language (as the vanilla C++ without STL) doesn't have a string type. There is a compiler feature that automatically converts text between double quotes "..." to a constant char array (which is null terminated), leading to this very common mistake when handling strings in C/C++. – jv42 Oct 14 '10 at 14:19
  • There are also string library functions, which operate on null-terminated arrays of `char`. – David Thornley Oct 14 '10 at 15:50
  • 3
    More properly, a string value is *represented* by a sequence of characters followed by a 0 terminator. These sequences are stored as arrays of `char` (string *literals* are stored as arrays of `char` in C, `const char` in C++). – John Bode Oct 14 '10 at 16:35
5

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.

Except when it is the operand of either the sizeof or & operators, or when it is a string literal being used to initialize another array in a declaration, an expression with type "N-element array of T" will have its type implicitly converted (decay) to type "pointer to T", and the value of the expression will be the address of the first element of the array.

So when you write

if (argv[1] == "-hello")

the compiler implicitly converts the expression "-hello" from type "7-element array of char" to "pointer to char" (argv[1] is already a pointer type), and the value of the expression is the address of the character '-'. So what == winds up comparing are two pointer values, which are (most likely) never going to be equal since "-hello" and argv[1] (most likely) occupy different regions in memory.

This is why you have to use library functions like strcmp() to compare string values.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • In C, string values (including string literals) are represented as arrays of `char` **which include** a 0 terminator ... – pmg Mar 17 '16 at 16:33
3

Because C strings don't exist as such. They are char arrays ending in a \0.

The equality operator == will test that the pointer to the first element of the array are the same. It won't compare lexicographically.

On the other hand "-hello" == "-hello" may return non zero, but that doesn't mean that the == operator compares lexicographically. That's due to other facts.

If you want to compare lexicographically, you can always do this:

#define STR_EQ(s1,s2)    \
   strcmp(s1,s2) == 0

I see that you tagged as C++. So you could do this:

 std::string arg1 ( argv[1] );
 
 if (arg1 == "-hello"){
    // yeahh!!!
 }
 else{
    //awwwww
 }
halfer
  • 19,824
  • 17
  • 99
  • 186
Tom
  • 43,810
  • 29
  • 138
  • 169
2

Strings are not native types in C. What you are comparing in that example are two pointers. One to your first argument, and the other is a static character array with the contents of "-hello".

You really want to use strncmp or something similar.

kanaka
  • 70,845
  • 23
  • 144
  • 140
1

When you're using ==, you're comparing pointers. That is, it will return true if the two operands refer to the same string in memory. Therefore, it's unsuitable for use in comparing strings lexicographically.

waffle paradox
  • 2,755
  • 18
  • 19
0

Because C strings are array of characters. Arrays are simply pointers to the first element in the array, and when you compare two pointers using == it compares the memory address they point to, not the values that they point to.

Anthony
  • 9,451
  • 9
  • 45
  • 72
  • 1
    [Arrays are not just pointers](http://publications.gbdirect.co.uk/c_book/chapter5/arrays_and_address_of.html), sheesh. – detly Oct 14 '10 at 13:32
  • @detly: Easy mistake to make, considering that arrays decay into pointers on almost any excuse. – David Thornley Oct 14 '10 at 15:51
  • @David Thornley: Even so, it's best to get the terminology correct. C's confusing enough without getting the basics wrong. – John Bode Oct 14 '10 at 16:56
  • My wording was a little harsh, sorry. But still, it's not. There are times when that assumption will really bite you. – detly Oct 15 '10 at 03:23