0

I'm trying to compare two char pointers:

char * x;
char * y;
   
x = "Hesham";
y = "Hesham";
   
printf("%d %d \n", &x, &y);
   
if(x==y)
{
  printf("=\n");
}
else
{
  printf("!=\n");
}

The execution result is:

2293368 2293360
=
  1. How come the two pointers are of different addresses and the operation == returns true?

  2. Why didn't the compiler store the string literal Hesham just once and use its address twice for x and y?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Hesham Eraqi
  • 2,444
  • 4
  • 23
  • 45
  • Did you mean to use `strncmp()`? – πάντα ῥεῖ May 29 '14 at 14:08
  • No, I didn't mean it. – Hesham Eraqi May 29 '14 at 14:08
  • 3
    Change the printf to `printf("%d %d \n", x, y);` and they should be equal. Also, you should use `%p` to print a pointer. – 001 May 29 '14 at 14:10
  • What Johnny said. And this is not a duplicate. The other question is about strings, this one is about pointers that just happen to be char pointers. Edit: and I should have refreshed sooner. – Mr Lister May 29 '14 at 14:11
  • @JohnnyMopp Thanks for the hint. I tried it and it also produced two different addresses. Then the equal sign! – Hesham Eraqi May 29 '14 at 14:12
  • I'm sorry, I should have printed : `printf("%d %d \n", x, y);` Not `&x` and `&y`. To see the address they point to. Thanks :) – Hesham Eraqi May 29 '14 at 14:25
  • 1
    Both `printf("%d %d \n", &x, &y)` and `printf("%d %d \n", x, y)` invoke undefined behavior as they pass arguments of the wrong type for the format `%d`, which expects an argument of type `int`. You should use `printf("%p %p", (void*)x, (void*)y)`. – Pascal Cuoq May 29 '14 at 14:32
  • @PascalCuoq You are right. I just meant I should used it without the **&**. – Hesham Eraqi May 29 '14 at 14:33

4 Answers4

12

How come the two pointers are of different addresses and the operation == returns true?

&x and &y are the addresses of the pointer variables rather than the addresses of the string. Since x and y are different variables, they have different addresses.

You then compare the values of x and y which happen to be the same because the compiler has noticed that the two string literals have the same value and only stored a single copy of the literal.

Why didn't the compiler store the string literal "Hesham" just once and use its address twice for x and y?

It did. That's why x == y evaluates as true.


One other point to make is that you should use the %p format specifier when printing pointers.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

It depends on a compiler option whether the compiler will store equal string literals as separate literals or as one literal/ Usually by default compilers store equal string literals as one string literal that to minimize the memory usage.

In these statements

   x = "Hesham";
   y = "Hesham";

you assign the same address of the first character of the string literal to variables x and y. As the compiler stores these two string literals as one string literals then it is obvious that x == ythat is x and y were assigned the same value.

However if you would set on the option of the compiler to force the compiler to store equal string literals as separate literals then the result of expression x == y would be equal to false. If you want to compare the string literals you have to write

if ( strcmp( x, y ) == 0 ) { /*...*/ }
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I'm sorry, I should have printed : `printf("%d %d \n", x, y);` Not `&x` and `&y`. To see the address they point to. Do you know that compiler options for ARM ? I have searched a lot for it and didn't find it. – Hesham Eraqi May 29 '14 at 14:27
1

According to The C++ Programming Language by Bjarne Stroustrup, He said

Whether two identical string literals are allocated as one array or as two is
implementation-defined.

I think it also works for C given that C++ is based on C99. In your case, only one of them is allocated and is used twice, which means x and y points to the identical string.

user3647351
  • 165
  • 7
  • 1
    In the C99 standard, whether `"foo" == "foo"` is unspecified, which is much weaker than “implementation-defined”. I am very surprised at the quote you found and in any case, it should probably not be considered normative. – Pascal Cuoq May 29 '14 at 14:27
  • 1
    I had a draft of the C++ standard dated from 2005 lying around and it indeed says “Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation-defined” (2.13.4:2). The corresponding C99 mention is “String literals, and compound literals with const-qualified types, need not designate distinct objects.”, which does not force an implementation to document its behavior or to make it consistent. (C99 6.5.2.5:8) – Pascal Cuoq May 29 '14 at 14:40
  • @PascalCuoq I don't think that it _must_ be treated as _unspecified_, which is rather intended for the case where _the exact behavior is unpredictable for fundamental reasons_ as Bjarne Stroustrup describes. Clearly, the value of a variable assigned to from two threads unless some synchronization mechanism has been employed is unpredictable. However it seems whether or not two identical string literals have a same address can be easily handled by each implementation. – user3647351 Jun 01 '14 at 12:45
  • If the C99 standardization committee wanted C99 programmers to treat string literals identity as implementation-defined, it would not have listed “Whether two string literals result in distinct arrays” under section “J.1 Unspecified behavior”. What else do you need? The title of the section is “Unspecified behavior” and the item under it is “Whether two string literals result in distinct arrays”. – Pascal Cuoq Jun 01 '14 at 13:20
  • @PascalCuoq Mis-understanding here. I'm not talking about the C99, rather about what you said _in any case, it should probably not be considered normative_. I thought you wanted to say that it should be _unspecified_ in C++ as is in C99. – user3647351 Jun 01 '14 at 14:12
0

There's an optimization technique called "string pooling" where the compiler may try to store identical string literals at the same memory location. This may or may not be active, depending on compiler and optimization settings.

Example:

#include <stdio.h>

int main()
{
  char* s1 = "hello";
  char* s2 = "hello";
  if(s1==s2)
    puts("same");
  else
    printf("%s is not %s", s1, s2);
}

Default output gcc x64 12.1:

same

Default output MSVC x64 19.32:

hello is not hello
Lundin
  • 195,001
  • 40
  • 254
  • 396