C++ 字符串文字唯一性要求
我一直理解字符串文本的存储是由实现定义的,因此编译器可以自由地汇总多个文本,例如,给定C++ 字符串文字唯一性要求,c++,C++,我一直理解字符串文本的存储是由实现定义的,因此编译器可以自由地汇总多个文本,例如,给定 static const char* foo = "blah"; static const char* bar = "blah"; foo和bar可以指向同一个内存。但是,我不知道这是否也是真的: static const char foo[] = "blah"; static const char bar[] = "blah"; 在第二种情况下,您声明了两个数组,每个数组都有不同的地址。所以不,地址会不
static const char* foo = "blah";
static const char* bar = "blah";
foo和bar可以指向同一个内存。但是,我不知道这是否也是真的:
static const char foo[] = "blah";
static const char bar[] = "blah";
在第二种情况下,您声明了两个数组,每个数组都有不同的地址。所以不,地址会不一样 您可以通过打印
foo
和bar
的地址轻松测试它(在这两种情况下,&foo!=&bar
,但在第一种情况下,这只意味着指针位于不同的位置,而在第二种情况下,这意味着数组位于不同的位置:(void*)&foo==(void*)&foo[0]
对于数组情况)格式良好的程序无法判断foo
和blah
是否存储在同一地址,因此我相信优化器可以将常量折叠在一起
[expr.rel]
(草案3225)规定:
如果同一类型的两个指针p
和q
指向不同的对象,而这些对象不是同一类型的成员
对象或同一数组的元素或不同的函数,或者如果其中只有一个为null
,则结果
在pq
中,p=q
未规定
[expr.eq]
说:
==
(等于)和=
(不等于)运算符具有相同的语义限制、转换和
结果类型为关系运算符,但优先级和真值结果较低
[expr.add]
说:
当两个指向同一数组对象元素的指针相减时
(剪报)
除非两个指针都指向同一数组对象的元素,或者
超过数组对象的最后一个元素一次,则行为未定义
脚注:这肯定是错误的,但这是我对标准内容的解释。我希望看到C++标准中否决这种语言的部分 我想可能是这样的:
[intro.object]
说:
两个既不是零位场也不是零基类子对象的不同对象
尺寸应具有不同的地址
[expr.eq]
说:
如果相同类型的两个指针比较相等,则
只有当它们都为null时,它们都指向同一个函数,或者都表示相同的地址
总之,是的,你可以判断数组是否折叠,所以它们不可能被折叠。但是大多数判断方法都有未指定的结果,您必须使用
=
或=代码>直接在指针上。正如@aschelper所指出的,std::less及其关系也将起作用。在第二种情况下,这两个变量实际上是数组,因此它们肯定指向不同的位置
static const char foo[] = "blah";
static const char bar[] = "blah";
cout << sizeof(foo) << " : " << (void*)foo << endl;
cout << sizeof(bar) << " : " << (void*)bar << endl;
请参见此处的输出:
(运行时,地址可能与上面显示的地址不同)
然而,在第一种情况下,两者都是指针,都指向相同的位置(对于大多数编译器)
你注意到两个指针的地址都是一样的吗
见:@Ben Voight引用了该标准: [intro.object]说:
两个既不是位场也不是零大小的基类子对象的不同对象应具有不同的地址 但标准中还有另一条同样重要的规则:似乎规则 也就是说,该标准保证您观察地址的两个不同对象是不同的 但是,据我所知,如果编译器能够证明你没有观察到一个对象的地址,它就可以将它与现有的对象合并(因为你没有观察到它的地址,你就不会意识到!)
这可能是一个典型的测量干扰实验的例子吗:)?一个结构良好的程序实际上可以告诉我们
foo
和bar
是截然不同的不同对象,因此它们必须有不同的地址。一个格式良好的程序可以获得这两个对象的地址并进行比较,它会注意到差异。你应该能够用const char*A=foo,b=bar来分辨;std::cout@Ben-我引用的是C99(不是C++)标准,但是:“两个指针比较相等,当且仅当两个指针都是空指针时,它们都是指向同一对象的指针(包括指向对象的指针和开头的子对象)或函数,两者都是指向同一数组对象的最后一个元素的指针,或者一个是指向一个数组对象末尾的指针,另一个是指向恰好位于地址空间中第一个数组对象之后的另一个数组对象的开头的指针。)”另一种可移植的测试方法:使用std::less
检查等价关系。正确,尽管用于初始化它们的实际常量可能仍然被合并。另一方面,事情甚至比“实现细节”更复杂,常数是否在同一个翻译单元中甚至可能会产生差异。例如,我的gcc 4.5副本会像第一个例子一样,在同一个单元内,而不是在不同的单元内(链接到一个程序中)愉快地合并常量。你不能确定地说,一个优化是不允许的,因为一个编译器选择不这样做。
5 : 0x8048a99
5 : 0x8048a94
static const char *foo = "blah";
static const char *bar = "blah";
cout << sizeof(foo) << " : " << (void*)foo << endl;
cout << sizeof(bar) << " : " << (void*)bar << endl;
4 : 0x8048a94
4 : 0x8048a94