我正在使用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
),类型就可以互换。
有人可以提供我可以查看的参考,以澄清这些问题吗?
感谢。
答案 0 :(得分:12)
这在C ++中仍然适用。如果您的编译器在您描述第一个案例时抱怨,那么它就是不符合的。
要解释您的第二个案例,了解实际情况非常重要。数组类型的表达式可以隐式转换为相应的指针类型,即:T[n]
- > T*
。但是,如果T
本身是一个数组,则不会特别处理此情况,并且数组到指针衰减不会传播。因此T*[n]
会衰减到T**
,但T[x][y]
只会衰减到T[y]*
,而不会再衰减。{/ p>
从实现的角度来看,这是有道理的,因为如果允许的话,进一步衰减会给T**
,它是指向指针的指针;而2D C数组并未实现为锯齿状数组(即指向数组的指针数组) - 它们形成单个连续的内存块。所以,数组中没有T*
“取”地址来给你T**
。对于允许的情况,典型的实现只是将数组的地址作为一个整体并将其转换为指向单个元素的指针类型(当底层指针表示对于所有类型都相同时,通常情况下,此转换是一个在运行时没有操作。)
此处的规范性引用是ISO C ++ 03,4.2 [conv.array] / 1:
“NT的数组”或“T的未知边界数组”类型的左值或右值可以转换为“指向T的指针”的右值。结果是指向数组的第一个元素的指针。
答案 1 :(得分:1)
void f2(char* p[]){
编译器抱怨“
cannot convert char (*)[] to char**...
”
奇怪。 char(*)[]
是指向字符数组的指针,但在您的代码段中,该函数具有char *p[]
参数,这意味着指向char的指针数组!这些类型确实不同(因为数组元素具有不同的大小),更不用说您的代码片段完美编译了。你真的拼错了。
夏洛克·福尔摩斯模式:或者是否涉及到typedef? ; - )
void f1(char** p){;}
typedef char type[];
void f2(type * p){
f1(p);
}
这实际上无法编译并产生您所引用的错误。