113
void main() { if("a" == "a") printf("Yes, equal"); else printf("No, not equal"); } 

Why is the output No, not equal?

23
  • 101
    void main ??? Ew... Commented Jan 30, 2011 at 15:59
  • 49
    Embedded C compilers allow void main() because there may not be any operating system to give a return code to. Commented Jan 30, 2011 at 20:20
  • 26
    How can a question like this get upvoted so often? It's really not that interesting ... I mean, that strings are arrays and arrays are pointers is really an old hat in C, isn't it? Commented Jan 31, 2011 at 2:27
  • 65
    @Felix, it's a concisely-written question that address a common point of confusion for newcomers to the language. SO isn't for experts only - it's for beginners as well, and targeted questions like this are good for referring beginners to in the future. Commented Jan 31, 2011 at 3:00
  • 38
    @Felix: You are wrong. arrays are not pointers Commented Jan 31, 2011 at 20:52

11 Answers 11

211

What you are comparing are the two memory addresses for the different strings, which are stored in different locations. Doing so essentially looks like this:

if(0x00403064 == 0x002D316A) // Two memory locations { printf("Yes, equal"); } 

Use the following code to compare two string values:

#include <string.h> ... if(strcmp("a", "a") == 0) { // Equal } 

Additionally, "a" == "a" may indeed return true, depending on your compiler, which may combine equal strings at compile time into one to save space.

When you're comparing two character values (which are not pointers), it is a numeric comparison. For example:

'a' == 'a' // always true 
Sign up to request clarification or add additional context in comments.

12 Comments

GCC also has the options -fmerge-constants and -fno-merge-constants to enable/disable string and floating-point constant merging across translation units, though on some GCCs it seems that constant merging is always enabled regardless of that option.
It would work if you use 'a' instead of "a". The first is a char, which is actually a numeric value.
@GolezTrol: in C, the literal 'a' actually has int type. :-) Also, pointers don't have to be numeric values.
int is numeric too, isn't it? But I thought chars were Byte. Int is 4 bytes. Pointers themselves are integer as well. They contain the address of a bunch of data (data that indeed doesn't have to be numeric).
'a' == 'A' // not true ... MySQL begs to differ.
|
52

I'm a bit late to the party, but I'm going to answer anyway; technically the same bits, but from a bit different perspective (C parlance below):

In C, the expression "a" denotes a string literal, which is a static unnamed array of const char, with a length of two - the array consists of characters 'a' and '\0' - the terminating null character signals the end of the string.

However, in C, the same way you cannot pass arrays to functions by value - or assign values to them (after initialization) - there is no overloaded operator == for arrays, so it's not possible to compare them directly. Consider

int a1[] = {1, 2, 3}; int a2[] = {3, 4, 5}; a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for // "identity", but not for their values. In this case the result // is always false, because the arrays (a1 and a2) are distinct objects 

If the == is not comparing arrays, what does it actually do, then? In C, in almost all contexts - including this one - arrays decay into pointers (that point to the first element of the array) - and comparing pointers for equality does what you'd expect. So effectively, when doing this

"a" == "a" 

you are actually comparing the addresses of first characters in two unnamed arrays. According to the C standard, the comparison may yield either true or false (i.e. 1 or 0) - "a"s may actually denote the same array or two completely unrelated arrays. In technical terms, the resulting value is unspecified, meaning that the comparison is allowed (i.e. it's not undefined behavior or a syntax error), but either value is valid and the implementation (your compiler) is not required to document what will actually happen.

As others have pointed out, to compare "c strings" (i.e. strings terminated with a null character) you use the convenience function strcmp found in standard header file string.h. The function has a return value of 0 for equal strings; it's considered good practice to explicitly compare the return value to 0 instead of using the operator `!´, i.e.

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2) 

Comments

48

According in C99(Section 6.4.5/6)

String Literals

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

So in this case it is unspecified whether both "a"s are distinct. An optimized compiler could keep a single "a" in the read-only location and both the references could refer to that.

Check out the output on gcc here

Comments

18

Because they are 2 separate const char*'s, pointers, no actual values. You are saying something like 0x019181217 == 0x0089178216 which of course returns NO

Use strcmp() instead of ==

2 Comments

String literals are not pointers, they are arrays. They decay to pointers on comparison, though.
@Gman true, sorry for not being really clear on that, tend to forget it :)
9

Simply put, C has no built-in string comparison operator. It cannot compare strings this way.

Instead, strings are compared using standard library routines such as strcmp() or by writing code to loop through each character in the string.

In C, a string of text in double quotes returns a pointer to the string. Your example is comparing the pointers, and apparently your two versions of the string exist at different addresses.

But it is not comparing the strings themselves, as you seem to expect.

Comments

3

Pointers.

The first "a" is a pointer to a null-terminated ASCII string.

The second "a" is a pointer to another null-terminated ASCII string.

If you're using a 32-bit compiler, I'd expect "a"=="a"-4. I've just tried it with tcc/Win32 though, and I get "a"=="a"-2. Oh well...

4 Comments

Why would you expect strings to be aligned to 4-byte boundary? They aren't ints. 2 is what I'd expect (if the compiler doesn't merge them), since each string is two bytes long, including the null terminator.
Some degree of alignment may, for instance, allow strcmp to run several bytes at a time. Some compilers do it, some don't, some do it only for strings longer than some minimum...
@Zack: how would they know the length of the string before actually comparing them?
I meant, some compilers align strings longer than some minimum.
1

You're comparing two memory address, so the result is not always going to be true. Did you try if('a' == 'a'){...}?

Comments

1

this question sets very good trail of explanation for all the beginers....
let me also contribute to it.....

as everybody above explained about , why you getting such output.

now if you want your prog. To print "yes equal" then

either use

if(strcmp("a", "a") == 0) { } 

or
do not use "a" as strings, use them as characters....

if('a'=='a') { printf ("yes Equal"); } 

in C characters are 1 byte short integer.......

1 Comment

Characters occupy only 1 byte, but character literals, such as 'a', are actually integers.
0

Some compilers have 'merge strings' option that you can use to force all constant strings to have the same address. If you would use that, "a" == "a" would be true.

Comments

0

if comparision between character is always in single quote, e.g.

if('a' == 'a') 

and C can't support string comparision like "abc" == "abc"

It's done with strcmp("abc","abc")

Comments

-5

This guy does not use variables. Instead, he uses temporarily text arrays: a and a. The reason why

void main() { if("a" == "a") printf("Yes, equal"); else printf("No, not equal"); } 

does not work of course, is that you do not compare variables.
If you would create variables like:

char* text = "a";
char* text2 = "a";

then you could compare text with text2, and it should be true

Maybe you shouldn't forget to use { and } =)

void main() { if("a" == "a") { printf("Yes, equal"); } else { printf("No, not equal"); } } 

1 Comment

"and it should be true" -- No. It is unspecified whether the string literals will be stored in the same memory location. Read the other answers.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.