string literal uniqueness requirements
I've always understood that the storage of string literals is implementation defined, so the compiler is free to roll up multiple literals such that, given
static const char* foo = "bla开发者_C百科h";
static const char* bar = "blah";
foo and bar can point to the same memory. However, I can't figure out if thats also true when:
static const char foo[] = "blah";
static const char bar[] = "blah";
A well-formed program cannot tell whether foo
and blah
are stored at the same address or not, so I believe that yes the optimizer could fold the constants together.
[expr.rel]
(draft 3225) says:
If two pointers
p
andq
of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them isnull
, the results ofp<q
,p>q
,p<=q
, andp>=q
are unspecified.
[expr.eq]
says:
The
==
(equal to) and the!=
(not equal to) operators have the same semantic restrictions, conversions, and result type as the relational operators except for their lower precedence and truth-value result.
[expr.add]
says:
When two pointers to elements of the same array object are subtracted
(snip)
Unless both pointers point to elements of the same array object, or one past the last element of the array object, the behavior is undefined.
FOOTNOTE: This has to be wrong, but it's my interpretation of what the standard says. I'd love to see the section of the C++ standard that overrules this language.
I think it may be this:
[intro.object]
says:
Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.
[expr.eq]
says:
Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address
So in conclusion, yes you could tell if the arrays were folded, so they can't be. But most ways of telling have unspecified results, you have to use ==
or !=
directly on pointers. As @aschelper points out, std::less
and its relations will also work.
In the second case, you are declaring two arrays, and each one of them will have a different address. So no, the addresses will not be the same.
You can easily test it by printing the address of foo
and bar
(in both cases, &foo != &bar
, but that in the first case only means that the pointers are in different locations, while in the second case it means that the arrays are in different locations: (void*)&foo == (void*)&foo[0]
for the array case)
@Ben Voight cited the Standard:
[intro.object] says:
Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.
But there is another rule in the standard that is equally important: the as-if rule.
That is, the standard guarantees that two distinct objects of which you observe the address shall be distinct.
But, as far as I understand it, if the compiler can prove that you do not observe the address of one object, it could merge it with an existing one (and since you do not observe its address, you would not realize it!)
Could it be a typical case of the measure perturbing the experiment :) ?
In the second case, the two variables are actually arrays, and hence they would definitely point to different location.
static const char foo[] = "blah";
static const char bar[] = "blah";
cout << sizeof(foo) << " : " << (void*)foo << endl;
cout << sizeof(bar) << " : " << (void*)bar << endl;
Output: (5 is the size of array)
5 : 0x8048a99
5 : 0x8048a94
See output here : http://www.ideone.com/hoH5v (when you run, the address may be different however than shown above)
In the first case however, both are pointers and would point to the same location (for most compilers)!
static const char *foo = "blah";
static const char *bar = "blah";
cout << sizeof(foo) << " : " << (void*)foo << endl;
cout << sizeof(bar) << " : " << (void*)bar << endl;
Output: (now 4 is the size of pointer)
4 : 0x8048a94
4 : 0x8048a94
Did you notice the address is same for both pointers?
See : http://www.ideone.com/keaoC
精彩评论