c++:函数 arg char** 与 char*[] 不同

Posted

技术标签:

【中文标题】c++:函数 arg char** 与 char*[] 不同【英文标题】:c++: function arg char** is not the same as char*[] 【发布时间】:2010-11-25 02:50:43 【问题描述】:

我正在使用 g++。我正在使用具有main(int,char**) 的代码,已重命名以便我可以调用它。我查看了Should I use char** argv or char* argv[] in C?,其中char** 据说等同于char* []。这在 c++ 函数调用中似乎不是真的。例如:

void f1(char** p);

void f2(char* p[])

   f1(p);

 //...`


编译器失败,抱怨“无法将char (*)[] 转换为char**...” 我希望将数组转换为调用指针的引用,但情况似乎并非如此:

void f3(char* [] p);

char caa[16][16];  
f3(caa);

也失败了。我曾假设只要间接级别相同(例如 char*** ptrchar[][][] carray ),类型是可以互换的。

谁能提供我可以查看的参考资料来澄清这些问题?

谢谢。

【问题讨论】:

【参考方案1】:

这在 C++ 中仍然成立。如果您的编译器如您在第一种情况下描述的那样抱怨,则它不符合要求。

为了解释您的第二种情况,了解实际发生的情况很重要。数组类型的表达式可以隐式转换为相应的指针类型,即:T[n] -> T*。但是,如果T 本身是一个数组,则不会对这种情况进行特殊处理,并且数组到指针的衰减不会传播。所以T*[n] 衰减为T**,但T[x][y] 只会衰减为T[y]*,不会再进一步​​了。

从实现的角度来看,这是有道理的,因为如果允许进一步衰减,将给出T**,它是指向指针的指针;而 2D C 数组没有实现为锯齿状数组(即指向数组的指针数组) - 它们形成一个连续的内存块。所以,没有T*“内部”数组可以获取地址给你T**。对于允许的情况,典型的实现简单地将数组的地址作为一个整体,并将其转换为指向单个元素的指针类型(当所有类型的底层指针表示相同时,通常情况下,这种转换是运行时无操作)。

这里的规范参考是ISO C++03, 4.2[conv.array]/1:

“N T 的数组”或“T 的未知边界数组”类型的左值或右值可以转换为“指向 T 的指针”类型的右值。结果是指向数组第一个元素的指针。

【讨论】:

实际上,我希望有一个 URL。我真的不明白你在说什么。 char** 是否等同于 char* []?在我看来:char c;字符* cp = &c; char** cpp = &cp; char* cparray[128]; cparray 和 cpp 不等价。不是 &T[n] -> T* 吗?我要解决的问题是函数调用参数中发生的转换。我现在使用的参考是 O'Reilly C++ in a Nutshell。 “ISO C++03, 4.2[conv.array]”是否在网络上可用,还是必须从出版商处订购的文档? 当应用于参数类型时,它是等价的,但在函数声明中。此外,char*[] 可以隐式转换为 char**,但 char[][] 不能。 ISO C++ 是 C++ 语言标准的规范 - 换句话说,是定义 C++ 语言准确语法和语义的主要文档。它不是合法免费提供的,但可以在此处以 30 美元的价格购买 PDF:techstreet.com/cgi-bin/basket?action=add&item_id=3626517 @cvsdave,特别是将*(int(*)[1])0*(int**)0 进行比较。第一个实际上不会崩溃,因为取消引用数组指针不会从内存中读取任何内容 - 它只是传递地址并且只会更改类型。但是,取消引用int** 指针将从特定地址(此处为空指针地址,这可能会崩溃)读取int*。因此,即使“间接级别”似乎相等 - 它们意味着对于数组和指针来说非常不同:) @cvsdave,通过一些间接级别的实验来补充帕维尔的好答案,您可以看看这个答案:***.com/questions/274865/pointer-question-in-c/…【参考方案2】:
void f2(char* p[])

编译器抱怨“cannot convert char (*)[] to char**...

奇怪。 char(*)[]指向字符数组的指针,但在您的代码 sn-p 中,函数有 char *p[] 参数,这意味着指向字符数组的指针!这些类型确实不同(因为数组元素的大小不同),更不用说你的代码 sn-p 完美编译了。你真的拼错了什么。

福尔摩斯模式:还是涉及到 typedef? ;-)

void f1(char** p);

typedef char type[];
void f2(type * p)
   f1(p);

这确实无法编译并产生您提到的错误。

【讨论】:

void f4(char* [16]); int mainint argc, char* argv) char caa[16][16]; f4(caa); 产生:a.cpp:在函数 int main(int, char**)': a.cpp:4: error: cannot convert char ()[16]' 到 char**' for argument 1' 到 `void f4(char*)' g++ 3.4.5 在 Redhat 5 上运行和Win XP 这让我很困惑。 好吧,Pavel Minaev 上面已经解释过,函数调用期间的char caa[16][16] 被转换为char (*caa)[16]。这意味着,*caa 表示字符的 array 并且等于 caa。您想要的是将其转换为(char *)caa[16],或者,不同的是,char *caa[16],由于我在帖子中解释的原因,这无法完成。

以上是关于c++:函数 arg char** 与 char*[] 不同的主要内容,如果未能解决你的问题,请参考以下文章

C++怎么把string 转换为char型数组

QML和C++混合编程中,在qml中向C++的char* 函数传递一个char*的字符串参数,qml不能识别char*的参数类型

C++ 函数形参里的const char作为返回值问题

C++ 从 'char' 到 'const char' 的无效转换

C++:char* 与 char(*)[]

为啥 char** 不能成为 C++ 中以下函数的返回类型?