Addresses of two char pointers to different string literals are same
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.
How can different strings have the same address
There is no guarantee that it will always be like this. In general, implementors maintain a literal pool maintaining each of the string literals only once, and then for multiple usages of the string literal the same address is being used. But one might implement it a different way - the standard does not pose a constraint on this.
Now your question: You are looking at the content of the two pointers pointing to the same string literal. The same string literal gave rise to the same value (they decayed into a pointer to the first element). But that address is same because of the reason stated in the first paragraph.
Also, I would emphasize providing the argument of the %p
format specifier with the (void*)
cast.
Why do (only) some compilers use the same address for identical string literals?
This is not undefined behavior, but unspecified behavior. For string literals,
The compiler is allowed, but not required, to combine storage for equal or overlapping string literals. That means that identical string literals may or may not compare equal when compared by pointer.
That means the result of A == B
might be true
or false
, on which you shouldn't depend.
From the standard, [lex.string]/16:
Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.
Why string literals are comparable with pointers?
It is unspecified behavior whether identical string literals can be considered the same and thus have the same address. So this is not portable behavior. From the draft C99 standard section 6.4.5
String literals:
It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. [...]
If you want to compare two string you should use strcmp.
Check whether equal string literals are stored at the same address
Is there any macro, in any C++ implementation, but mainly g++ and clang, whose definition guarantees that several equal string literals are stored at the same address?
- gcc has the
-fmerge-constants
option (this is not a guarantee) :
Attempt to merge identical constants (string constants and floating-point constants) across compilation units.
This option is the default for optimized compilation if the assembler and linker support it. Use -fno-merge-constants to inhibit this behavior.
Enabled at levels -O, -O2, -O3, -Os.
- Visual Studio has String Pooling (/GF option : "Eliminate Duplicate Strings")
String pooling allows what were intended as multiple pointers to multiple buffers to be multiple pointers to a single buffer. In the following code, s and t are initialized with the same string. String pooling causes them to point to the same memory:
char *s = "This is a character buffer";
char *t = "This is a character buffer";
Note: although MSDN uses char*
strings literals, const char*
should be used
- clang apparently also has the
-fmerge-constants
option, but I can't find much about it, except in the--help
section, so I'm not sure if it really is the equivalent of the gcc's one :
Disallow merging of constants
Anyway, how string literals are stored is implementation dependent (many do store them in the read-only portion of the program).
Rather than building your library on possible implementation-dependent hacks, I can only suggest the usage of std::string
instead of C-style strings : they will behave exactly as you expect.
You can construct your std::string
in-place in your containers with the emplace()
methods :
std::unordered_set<std::string> my_set;
my_set.emplace("Hello");
Ensure that char pointers always point to the same string literal
As Barry shows in their answer the behavior you want is not guaranteed. You're going to have to pay the cost of string comparisons, but you can at least avoid any memory allocations or writing a comparator by using a std::string_view
. A std::string_view
is a lightweight view of a string that holds a pointer to the string data and the size of the string and it has a built in operator <
that will do a lexicographical comparison. That would change your map to
std::map<std::string_view, something>
Is it safe to compare const char* with == in C/C++?
Is it safe to compare this value using a regular == as opposed to a strcmp?
No. It isn't safe in the sense that two string literals - even with same content - are not guaranteed to have the same storage address, and thus may compare different.
You can compare the address initially and only compare content if the address differs. You can return early if the address matches.
Why does == return true for character pointers?
Because the two addresses are the same. Your compiler included one copy of the string "Hello" in your program and made str1
and str2
both point to it.
The C standard specifies that string literals might or might not be distinct arrays in memory, and that undefined things might happen if you modify them in order to allow the compiler to do exactly this.
Related Topics
Building Glew on Windows with Mingw
Gmon.Out Is Not Written After Compiling with Gcc -Pg -G
While (1) VS. for (;;) Is There a Speed Difference
Find Out If String Ends with Another String in C++
Openprocess/Readprocessmemory/Writeprocessmemory/Closehandle Equivalent
Press Anykey to Continue in Linux C++
Headers Including Each Other in C++
Returning Temporary Object and Binding to Const Reference
Cannot Get Makefile to Build Each Object from Its Corresponding Source
Missing Lboost_Thread-Mt in Mongodb Cpp Driver (Ubuntu Server X64)
Effective C++ Item 23 Prefer Non-Member Non-Friend Functions to Member Functions
Get Computer Name and Logged User Name
Why Can't the Compiler Deduce the Template Type from Default Arguments