Comparing two char pointers like this char *a, *b; a == b;
is accepted by the compiler, but if you are using such a syntax to compare the string values, then you may not get the results you are expecting. Some times it may evaluate to true
or sometimes to false
. The reason is, the program checks whether a
and b
are pointing to the same address, and not for if they have the same string value. Consider the program below.
#include <stdio.h>
int main()
{
char* a = "test";
char* b;
if ((b="test") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
OUTPUT
Impossible
0x55b6bd52d004 0x55b6bd52d004
As you see from the output, the if
block is evaluated to true
. The reason is also in the output; a
and b
are pointing to a similar address. Why?
It comes from the string-pooling, one of the compiler optimization. Even though a
and b
are initialized at different points in the program, as they are referring to the same string constant, the string constant is initialized only once by the compiler.
Here is the objdump
of the executable.
$ objdump -s -j .rodata
a.out: file format elf64-x86-64
Contents of section .rodata:
2000 01000200 74657374 00496d70 6f737369 ....test.Impossi
2010 626c6500 54686f75 67687420 736f0025 ble.Thought so.%
2020 70202570 0a00 p %p..
test
is initialized only once. For a quick check, consider this program's output and its objdump
.
#include <stdio.h>
int main()
{
char* a = "test";
char* b;
if ((b="test1") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
OUTPUT
Thought so
0x557a96aa9004 0x557a96aa9009
objdump
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
2000 01000200 74657374 00746573 74310049 ....test.test1.I
2010 6d706f73 7369626c 65005468 6f756768 mpossible.Though
2020 7420736f 00257020 25700a00 t so.%p %p..
It is evident from the output that a
and b
are pointing to different locations, and both are having different string values that are initialized by the compiler separately. So, if a
and b
are having similar string values, does a==b
always evaluate to true? Consider the below program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* a = malloc(sizeof(char) * 5);
strcpy(a, "test");
char* b;
if ((b="test") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
OUTPUT
Thought so
0x5607d9938260 0x5607d91fb004
Even though the a
and b
are having the same string values, if
evaluate to false
. Why? The address a
is pointing, which is created by malloc()
belongs to the heap section of the executable, whereas the address b
is pointing belongs to the data section of the executable, and they are indeed different.
So what should we do to compare the string values?
Well, it is straight forward, there are already library functions which can perform this task. You can use them withstring.h
. Consider the below code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* a = malloc(sizeof(char) * 5);
strcpy(a, "test");
char* b = "test";
char* c;
if (strcmp((c="test"), a) == 0)
printf("Impossible\n");
else
printf("Thought so\n");
if (strcmp(b, a) == 0)
printf("Impossible\n");
else
printf("Thought so\n");
if (strcmp(b, c) == 0)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p %p\n", a, b, c);
return 0;
}
OUTPUT
Impossible
Impossible
Impossible
0x556debf41260 0x556deac28004 0x556deac28004
Irrespective of where a
, b
and c
are pointing if they all are having the same string values, then strcmp()
returns 0
.