c++ - 为什么我在一种情况下会收到带有字符串文字的弃用转换警告,而在另一种情况下却不会?

标签 c++ arrays string pointers string-literals

我正在学习 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";

在第二种情况下导致警告而不是第一种情况的这两个声明之间有什么不同?

最佳答案

当你写作时

char str1[] = "hello";

你是说“请给我一个包含字符串“hello”char数组,请选择数组的大小str1 是初始化它的字符串的大小。”这意味着 str1 最终存储了它自己的字符串 "hello" 的唯一拷贝。 str1 的最终类型是 char[6] - 五种用于 hello,一种用于空终止符。

当你写的时候

char *str2 = "world";

你是说“请给我一个类型为 char * 的指针,它指向字符串文字 "world"。”字符串文字 "world" 的类型为 const char[6] - 它是一个包含六个字符的数组(五个代表 hello,一个代表 null终止符),重要的是这些字符是 const 并且不能被修改。由于您使用 char * 指针指向该数组,因此您将丢失 const 修饰符,这意味着您现在(不安全地)拥有一个非 const 指向数据的 const 位的指针。

这里不同的原因是,在第一种情况下,您得到字符串 "hello"拷贝,所以您的数组是't const 不是问题。在第二种情况下,您没有获得 "hello" 的拷贝,而是获得了指向它的指针,并且由于您获得了指向它的指针,所以担心修改它可能是一个真正的问题。

换句话说,在第一种情况下,您会得到一个由六个字符组成的真实数组,其中包含 hello 的拷贝,因此如果您随后决定去改变那些角色。在第二种情况下,您将获得一个指向您不应修改的六个字符数组的指针,但您使用的是一个允许您改变内容的指针。

那么为什么 "world" 是一个 const char[6]?作为对许多系统的优化,编译器只会将 "world" 的一个拷贝放入程序中,并使文字 "world" 的所有拷贝都指向完全相同的位置内存中的字符串。这很好,只要您不更改该字符串的内容即可。 C++ 语言通过声明这些字符是 const 来强制执行此操作,因此改变它们会导致未定义的行为。在某些系统上,这种未定义的行为会导致诸如“哇,我的字符串文字中有错误的值!”之类的事情,而在其他系统上,它可能只是段错误。

关于c++ - 为什么我在一种情况下会收到带有字符串文字的弃用转换警告,而在另一种情况下却不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47106643/

相关文章:

c++ - 高效的字符串比较

java - 通过复选框添加/删除 ArrayList<String> 中的字符串

c++ - get_line可以直接填一个std::vector<std::string>吗?

c++ - is_transparent 在部分 key 方面的合法使用

c++ - 从表面减去封闭网格(CGAL?)

c++ - 如何使用 FLTK 在 Windows、Mac OS X 和 Linux 中使窗口透明?

php - 在 PHP 中将数组元素移动到顶部

java - 如何创建一个包含未知数量对象的变量?

java - HashMap 元素的 ArrayList 到 Array

c++ - 打印字符串的宏