Eug*_*sov 88 c++ string-literals string-interning language-lawyer
我可以'some'
在MSVC生成的汇编代码中看到两个文字,但只有一个有clang和gcc.这导致完全不同的代码执行结果.
static const char *A = "some";
static const char *B = "some";
void f() {
if (A == B) {
throw "Hello, string merging!";
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释这些编译输出之间的差异和相似之处吗?为什么即使没有请求优化,clang/gcc也会优化某些内容?这是某种未定义的行为吗?
我还注意到,如果我将声明更改为下面显示的声明,则clang/gcc/msvc根本不会"some"
在汇编代码中留下任何声明.为什么行为不同?
static const char A[] = "some";
static const char B[] = "some";
Run Code Online (Sandbox Code Playgroud)
son*_*yao 106
这不是未定义的行为,而是未指定的行为.对于字符串文字,
允许编译器(但不是必需的)将存储组合为相等或重叠的字符串文字.这意味着当通过指针进行比较时,相同的字符串文字可能会或可能不会比较相等.
这意味着结果A == B
可能是,true
或者false
你不应该依赖.
从标准,[lex.string]/16:
是否所有字符串文字都是不同的(即,存储在非重叠对象中)以及是否对字符串文字的连续评估产生相同或不同的对象是未指定的.
tob*_*i_s 35
其他答案解释了为什么你不能指望指针地址不同.然而,您可以轻松地以保证A
并且B
不比较相等的方式重写它:
static const char A[] = "same";
static const char B[] = "same";// but different
void f() {
if (A == B) {
throw "Hello, string merging!";
}
}
Run Code Online (Sandbox Code Playgroud)
不同的是A
和B
现在字符数组.这意味着它们不是指针,它们的地址必须是不同的,就像两个整数变量必须的那样.C++混淆了这一点,因为它使得指针和数组看起来可以互换(operator*
并且operator[]
看起来表现相同),但它们确实不同.例如,const char *A = "foo"; A++;
完全合法的东西,但const char A[] = "bar"; A++;
不是.
考虑差异的一种方法是char A[] = "..."
说"给我一块记忆并用...
随后的字符填充\0
",然后char *A= "..."
说"给我一个地址,我可以找到...
后面跟着的字符\0
".
归档时间: |
|
查看次数: |
6562 次 |
最近记录: |