当我使用MinGW运行此程序时,我输出为“=”
#include<iostream>
using namespace std;
int main()
{
char *str1 = "Hello";
char *str2 = "Hello";
if(str1==str2)
cout<<"=";
else
cout<<"!=";
return 0;
}
然而,从逻辑上讲,它应该是!=,因为这些是指针,它们指向不同的内存位置。当我在Turbo C ++中运行此代码时,我得到了!=
答案 0 :(得分:14)
你是对的,他们是指针。但是,它们是否指向不同的位置取决于实施。编译器只存储一次字符串文字并在代码中使用它的地址时使用它是完全有效的。
答案 1 :(得分:10)
无法保证两个指针指向不同的内存位置。也许是因为优化,或者编译器使用自己的规则......行为是“实现定义”。
根据标准(C ++11§2.14.5字符串文字):
是否所有字符串文字都是不同的(即存储 在非重叠对象中)是实现定义。
答案 2 :(得分:4)
这是预期的结果。您可以通过查看基础程序集来验证这一点。例如,如果我使用:
构建g++ -S ptr.c
然后您可以在文件输出(ptr.s)中看到以下内容:
.file "ptr.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "Hello\0" ; Note - "Hello" only appears once in
; this data section!
LC1:
.ascii "=\0"
LC2:
.ascii "!=\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
[... some stuff deleted for brevity ...]
LCFI5:
call ___main
movl $LC0, -12(%ebp) ; This sets str1
movl $LC0, -8(%ebp) ; This sets str2
movl -12(%ebp), %eax
我评论了两个关键位 - 在底层代码的rdata部分只有一个'Hello'的外观,你可以看到str1和str2都设置在最后,两者都指向同一个标签: LC0
。这是因为'Hello'是一个字符串文字,重要的是,常量。
正如其他人所指出的那样 - 根据标准,这是完全合法的。
答案 3 :(得分:2)
像"Hello"
这样的字符串文字的类型是 const char 的数组,因此,你指的是指向不允许的东西的两个指针更改。
C ++标准使编译器可以自由地将相同的常量值合并在一起(请注意,编译器不是必需的)。
相关:因此声明无效,必须修改为:
const char *str1 = "Hello";
const char *str2 = "Hello";
或者如果你想要
char const *str1 = "Hello";
char const *str2 = "Hello";
从右到左阅读时读得很好:
str1 is a pointer to const char
答案 4 :(得分:0)
char *str1 = "Hello";
- 这条线虽然允许(由许多编译器提供),但实际上这是一个坏主意。它基本上只允许与C向后兼容,实际写入* str1会导致未定义的行为。我建议找到编译器设置,当你这样做时会给你警告,如果你的编译器没有这样的警告找到一个新的编译器。
C ++标准为编译器和执行环境提供了关于"String literals"
存储位置的大量自由。他们可以使用指向"literal"
的{{1}}部分的指针作为"String literals"
的指针值,并将它们存储在内存中,当您尝试编辑它们时,它们就会出现段错误并不出人意料。
请注意,"literal"
执行的操作与char buf1[] = "Hello";
根本不同:它实际上使用字符char* str1 = "Hello";
初始化缓冲区buf1
。