为啥指向 char 的指针与指向 char 作为数组元素的指针的行为不同?

Posted

技术标签:

【中文标题】为啥指向 char 的指针与指向 char 作为数组元素的指针的行为不同?【英文标题】:why is pointer to a char behaving differently than a pointer to a char as array element?为什么指向 char 的指针与指向 char 作为数组元素的指针的行为不同? 【发布时间】:2017-10-09 08:51:55 【问题描述】:

我很好奇为什么这两段代码给出不同的输出

#include <iostream>
using namespace std;
int main()
    char *arr=new char;
    arr="monday";
    cout<<arr<<endl;//gives the output "monday"

    char *newArr=new char[3];//i want array of three pointers not the size of a string to be 2+1
    newArr[0]="monday";//err
    cout<<newArr[0]<<endl;


    system("pause");
    return 0;


我的意思是他们不是都指向首字母地址的指针

问题是“arr”和“newArr[0]”有什么区别

【问题讨论】:

【参考方案1】:

你遇到的麻烦比你意识到的要多......

char *arr=new char;
arr="monday";

您首先让arr 指向您分配的单个 字符。然后你重新分配arr 并使它指向其他地方(指向文字"monday" 的数组的第一个字符)。这会导致泄漏,因为您分配的原始内存丢失并且无法再访问。

至于

char *newArr=new char[3];
newArr[0]="monday";

这里你让newArr指向一个由三个单字符组成的“数组”,然后尝试让单字符newArr[0]指向字符串字面量。


有点不同,你想做什么

char* arr = new char;

基本上等价于

char arr[1];

还有

char* newArr = new char[3];

相当于

char newArr[3];

标准解决问题的方法当然是使用 C++ 标准 std::string 类。比如说

std::string arr;
arr = "monday";

再加上第二个std::vectorstd::array

std::array<std::string, 3> newArr;
newArr[0] = "monday";

最后,关于arrnewArr[0]的区别。一个是指向char 的指针,类型为char*。另一个是char(但newArr 是指向char 的指针,就像arr)。

【讨论】:

如果我可以问,为什么编译器甚至允许重新分配 arr @awashima 因为它不是无效的?如果你愿意,你可以让它指向任何地方。 C++不牵你的手,如果你想shoot yourself in the foot你可以做到。【参考方案2】:

它们不是都指向首字母地址的指针吗?

是的,arrnewArr 都是指向 C 样式字符串中初始字符的指针。但是,newArr[0] 根本不是指针,因此 C++ 不允许您为其分配 const char* 指针。

如果要获取指向newArr的首字符的指针,需要使用运算符&amp;,即&amp;newArr[0]。您将无法分配它,但您可以打印它:

const char *newArr = "monday";
cout <<  newArr[0] << endl; // prints m
cout << &newArr[0] << endl; // prints monday

请注意,代码中new 的两个赋值都会产生内存泄漏,因为你用另一个值覆盖了new 产生的值,而没有释放分配的内存。

【讨论】:

删除arr;删除 [] newArr;应该加吗? @awashima 如果您的代码以任何方式使用分配的值,这将是正确的。但是,它不会:您立即覆盖分配的指针。这就是为什么更好的选择是完全删除new,因为您的程序不使用它的结果。 好的,我明白了,我只想要两个,在我看来语义相同的代码块......但如果我做这样的事情(分配是动态分配数组并填充它一周中的天数) char (*arr)[12]=new char[7][12]; strcpy(arr[0],"星期一"); strcpy(arr[1],"星期二"); strcpy(arr[2],"星期三"); strcpy(arr[3],"星期四"); strcpy(arr[4],"星期五"); strcpy(arr[5],"星期六"); strcpy(arr[6],"星期日"); for(int i=0;i @awashima 您评论中的代码是正确的,它没有内存泄漏。【参考方案3】:

“arr”和“newArr[0]”有什么区别

简短的回答,与arr 不同,newArr[0] 不是指针,而是可以容纳一个字符。 newArr[i]*(newArr + i) 相同。您正在尝试将字符串放置到字符类型上。

【讨论】:

以上是关于为啥指向 char 的指针与指向 char 作为数组元素的指针的行为不同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥新的 Visual Studio 将字符串文字作为指向常量的指针?

swig char ** 作为指向 char * 的指针

在 C# String 构造函数 String(Char*) 中,为啥构造函数不期望指向字符数组的指针?

指向 char 指针数组的指针与指向 char 指针的指针(或 char** argv 与 char* (*argv)[])

为啥 const QString& 参数返回错误的 const char* 指向数据的指针

为啥指向 char 数组的指针必须需要 strcpy 才能为其数组分配字符而双引号分配不起作用?