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*** ptr
和 char[][][] 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*[] 不同的主要内容,如果未能解决你的问题,请参考以下文章
QML和C++混合编程中,在qml中向C++的char* 函数传递一个char*的字符串参数,qml不能识别char*的参数类型