开发者

string literal uniqueness requirements

开发者 https://www.devze.com 2023-02-15 15:14 出处:网络
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

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 and q 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 is null, the results of p<q, p>q, p<=q, and p>=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

0

精彩评论

暂无评论...
验证码 换一张
取 消