3
#include <stdio.h>

int main(){
    char a[] = "bar";
    char b[] = "bar";
    printf("%d\n", (a==b));

    char* x = "bar";
    char* y = "bar";
    printf("%d\n", (x==y));
 }  

Output :

0 
1

I know we can't compare C char arrays using the == operator as it compares memory locations, but why does it work in the second case ?

Ahmed Karaman
  • 523
  • 3
  • 12
  • 1
    Well it works in the *first* case, because the compiler identified the two `"bar"` string literals as being identical, and decided to save space by sharing the storage, and having both `a` and `b` point to it. I don't know why it didn't also do this in the case of `x` and `y`, though. – Alexander Nov 17 '17 at 03:10
  • [how to merge duplicated or multiplicated string literals into one in GCC](https://stackoverflow.com/q/31977606/995714), [Why is “a” != “a” in C?](https://stackoverflow.com/q/4843640/995714), [C optimisation of string literals](https://stackoverflow.com/q/11399682/995714) – phuclv Nov 17 '17 at 04:23

3 Answers3

5

In the first case, as you defined two arrays, the compiler allocated two separate storage for them, so a and b are not equal.

But, for the second case, as you initialized two pointers with the same string literal, the compiler found them the same string, and point the two pointers into the same address which is the start address of that string literal ("bar"). However, as @David said, this is not happened necessarily, and in some situation, removing some optimization, or based on some compiler, x and y might not be the same.

OmG
  • 18,337
  • 10
  • 57
  • 90
3

The output makes sense because the memory storage for the arrays are not equal. For the char's, their literal characters are compared. Try running this example.

int main(void) {
    char a[] = "bar";
    char b[] = "bar";

    printf("Arrays Test: %x == %x ? %d\n",&a,&b,(a==b));


    char* x = "bar";
    char* y = "bar";

    printf("Literals Test: %x == %x ? %d, however x == y ? %d\n",&x,&y, (&x==&y),(x==y));

    return 0;
}

This online runnable example shows that the char's memory references are not the same.

If you wanted to see if the array's content is equal, you would need to call every char in the array and compare it to the secondary array manually. You could potentially end execution faster by checking the sizes of the array against each other.

An additional point is that "pointerizing" the chars or arrays makes no difference in this scope of comparison.

Bennett Yeo
  • 819
  • 2
  • 14
  • 28
1

This is implementation-dependent

In the 1st case, a and b have separate storage space, so their address won't be equal.

However, the compiler may identify that the strings x and y are pointing to is identical, so it may optimize by making them point to the same location, since you can't modify it. However, as the standard does not require to do so, you can't rely on the result. It's an optional optimization. The compiler can still generate two identical strings and make x and y point to them separately.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • 1
    Not undefined behavior, since both `x` and `y` contain valid addresses; just implementation-dependent. – ad absurdum Nov 17 '17 at 03:31
  • @DavidBowling Go get some reference. – iBug Nov 17 '17 at 03:34
  • 2
    A reference for what? The pointers `x` and `y` are well-defined, whether the compiler stores one or two strings for them, and the pointer comparison is valid. No UB. If it eases your mind, you could look over the [list of undefined behaviors from Annex J.2](http://port70.net/~nsz/c/c11/n1570.html#J.2) to find that this is not listed among them ;) – ad absurdum Nov 17 '17 at 03:37