Addresses of two char pointers to different string literals are same

#include<stdio.h>
#include<string.h>


int main()
{
char * p = "abc";
char * p1 = "abc";
printf("%d %d", p, p1);
}

When I print the values of the two pointers, it is printing the same address. Why?

6887 次浏览

Your compiler seems to be quite clever, detecting that both the literals are the same. And as literals are constant the compiler decided to not store them twice.

It seems worth mentioning that this does not necessarily needs to be the case. Please see Blue Moon's answer on this.


Btw: The printf() statement should look like this

printf("%p %p", (void *) p, (void *) p1);

as "%p" shall be used to print pointer values, and it is defined for pointer of type void * only.*1


Also I'd say the code misses a return statement, but the C standard seems to be in the process of being changed. Others might kindly clarify this.


*1: Casting to void * here is not necessary for char * pointers, but for pointers to all other types.

because string "abc" itself a address in memory. when u write "abc" again it store same address

When you create a string literal ("abc"), it is saved into a memory, which contains string literals, and then it's being reused if you refer to the same string literal, thus both pointers pointing to the same location, where the "abc" string literal is stored.

I've learned this some time ago so I might not have explained it really clearly, sorry.

String literals in the code are stored in a read-only data segment of the code. When you write down a string literal like "abc" it actually returns a 'const char*' and if you had all the compiler warnings on it would tell you that you are casting at that point. You are not allowed to alter those strings for the very reason you have pointed out in this question.

Your compiler has done something called "string pooling". You specified that you wanted two pointers, both pointing to the same string literal - so it only made one copy of the literal.

Technically: It should have complained at you for not making the pointers "const"

const char* p = "abc";

This is probably because you are using Visual Studio or you are using GCC without -Wall.

If you expressly want them to be stored twice in memory, try:

char s1[] = "abc";
char s2[] = "abc";

Here you explicitly state that you want two c-string character arrays rather than two pointers to characters.

Caveat: String pooling is a compiler/optimizer feature and not a facet of the language. As such different compilers under different environments will produce different behavior depending on things like optimization level, compiler flags and whether the strings are in different compilation units.

Whether two different string literals with same content is placed in the same memory location or different memory locations is implementation-dependent.

You should always treat p and p1 as two different pointers (even though they have the same content) as they may or may not point to the same address. You shouldn't rely on compiler optimizations.

C11 Standard, 6.4.5, String literals, semantics

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.


The format for printing must be %p:

  printf("%p %p", (void*)p, (void*)p1);

See this answer for why.

This actually depends on which compiler you are using.

In my system with TC++ 3.5 it prints two different values for the two pointers i.e. two different addresses.

Your compiler is designed s.t it will check for existence of any value in the memory and depending on its existence it will reassign or use the same reference of the previously stored value if the same value is referred to.

So don't think about it too much as it depends on the way the compiler parses the code.

THAT'S ALL...

As others have said, the compiler is noticing that they have the same value, and so is deciding to have them share data in the final executable. But it gets fancier: when I compile the following with gcc -O

#include<stdio.h>
#include<string.h>


int main()
{
char * p = "abcdef";
char * p1 = "def";
printf("%d %d", p, p1);
}

it prints 4195780 4195783 for me. That is, p1 starts 3 bytes after p, so GCC has seen the common suffix of def (including the \0 terminator) and done a similar optimisation to the one you have shown.

(This is an answer because it's too long to be a comment.)

you are use string literal,

when complier catch two same string literal,

it give the same memory location, therefore it show same pointer location./

It is compiler optimization but forget optimization for portability. Sometime compiled codes are more readable than actual codes.