2017-11-04 71 views
0

我正在学习C++。在据我所知这里所示,该节目,str1str2店的每一个相关的字符串的第一个字符地址:为什么我会在一种情况下得到一个带有字符串文字的弃用转换警告,而不是另一种情况?

#include <iostream> 
using namespace std; 

int main() 
{ 
    char str1[]="hello"; 
    char *str2="world"; 
    cout<<str1<<endl; 
    cout<<str2<<endl; 
} 

然而,str1不给任何警告,而与str2我得到这个警告:

warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] 
    char *str2="world"; 

这两个声明有什么区别,导致在第二种情况下警告,但不是第一种?

+0

“str1和str2应存储字符串的第一个字符的地址”。这不是真的。 'str1'存储整个字符串本身的副本。它不存储任何“地址”。另一方面,'str2'确实存储地址。 – AnT

+0

HI ANT,如果副本存储在str1中,那么将存储另一个“hello”副本?如果我们修改str1复制str str [0] ='H',这个改变会影响另一个副本吗? – Bahubali

+0

最初的''hello''存储在静态和不可修改的内存中。当你执行'str [0] ='H''时,你修改存储在'str1'中的副本。原稿保持不变。 – AnT

回答

3

当你写

char str1[] = "hello"; 

你说:“请让我的char s表示包含字符串"hello"数组,请选择该阵列str1的尺寸为字符串的大小对其进行初始化“。这意味着str1最终会存储自己的字符串"hello"的唯一副本。 str1的最终类型是char[6] - 对于hello有五个,对于空终止符有一个。

当你写

char *str2 = "world"; 

你说:“请让我char *类型的指针指向字符串字面"world"。”字符串文字"world"的类型为const char[6] - 它是一个由6个字符组成的数组(其中hello五个,一个用于空终止符),重要的是那些字符是const,并且无法修改。由于您使用char *指针指向该阵列,因此您将丢失const修饰符,这意味着您现在(不安全)的指针具有指向const位数据的非const指针。

的原因,事情在这里不同的是,在第一种情况下,你所得到的字符串"hello"副本,所以实际上你的阵列是不是const是没有问题的。在第二种情况下,您没有获得"hello"的副本,而是获取指向它的指针,并且由于您正在获得指向它的指针,因此修改它可能是一个真正的问题。

换句话说,在第一种情况下,你会得到一个由6个字符组成的诚实善良数组,其中包含hello的副本,所以如果您决定去修改这些字符,则没有任何问题。在第二种情况下,你得到一个指向一个你不应该修改的六个字符的数组,但是你使用了一个允许你改变事物的指针。

那么为什么"world"const char[6]?作为许多系统的优化,编译器只会将"world"的一个副本放入程序中,并且将文字"world"的所有副本指向内存中完全相同的字符串。这很好,只要你不改变那个字符串的内容。 C++语言通过说这些字符是const来强制执行此操作,所以对它们进行变异会导致未定义的行为。在某些系统中,这种未定义的行为会导致诸如“whoa,我的字符串文字具有错误值!”等情况,而在其他系统中,它可能只是段错误。

+0

你好,这是一个非常好的答案。我可以知道“你好”和“世界”都被视为字符串文字吗?或者只有“世界”被认为是字符串文字(bcz它被分配给char *)? – Bahubali

+0

“hello”和“world”都是字符串文字。这里的区别出现在你分配这些文字的基础上。在第一种情况下,赋值被视为数组初始化,所以创建了一个文字副本。第二,它是指针初始化,所以没有复制。 – templatetypedef

0

问题是,您正试图将字符串文字(类型为const char *)转换为char *。

+0

虽然这是真的,但我不认为它解决了OP为什么第一个选项不起作用的问题。 – templatetypedef

相关问题