在parseFunc()中,如果我通过传递&tIpArray调用loadFunc(),则在使用C作为编译器时(在onlinegdb.com中)它可以正常编译,但在更高版本的C编译器(gcc-bin / 4.9)中抱怨如下。 4 / gcc)。
工作中的错误类似于在onlinegdb中将语言用作C ++进行编译时看到的错误。有人可以告诉我为什么4.9.4 gcc C编译器不喜欢&以及正确的处理方式吗?
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct _MyStruct
{
char string[72];
}MyStruct;
int loadFunc(MyStruct** ipData, int counter)
{
MyStruct **currentVal = ipData;
MyStruct *ipPtr = NULL;
printf("%p\n", currentVal);
for(int i=0; i<counter; i++)
{
ipPtr = currentVal[i];
printf("Line-%d - %s - %p\n", i+1, ipPtr->string, ipPtr);
}
}
int parseFunc()
{
MyStruct* tIPArray[3];
for(int i=0; i< 3; i++)
{
tIPArray[i] = 0;
tIPArray[i] = (MyStruct*) calloc(1, sizeof(MyStruct));
snprintf(tIPArray[i]->string, 72, "Test-String-%d", i+101);
}
for(int i=0; i<3; i++)
{
printf("Line-%d %p-%p- %s\n", i+1, &tIPArray[i], tIPArray[i], tIPArray[i]->string);
}
// call the load/ print loadFunc
loadFunc(&tIPArray, 3);
}
int main()
{
printf("Hello World\n");
parseFunc();
return 0;
}
以下是我上班时遇到的错误
error: passing argument 1 of 'loadFunc' from incompatible pointer type [-Werror] loadFunc(&tIPArray, 3); note: expected 'struct MyStruct **' but argument is of type 'struct MyStruct * (*)[(sizetype)((int)((short unsigned int)getMaxAddressObjects() / 4u))]' int loadFunc(MyStruct **ipData, int counter)
在onlinegdb.com中将其构建为C ++文件时出现以下错误
main.cpp: In function ‘int parseFunc()’: main.cpp:49:38: error: cannot convert ‘MyStruct * (*)[3] {aka MyStruct * (*)[3]}’ to ‘MyStruct ** {aka MyStruct **}’ for argument ‘1’ to ‘int loadFunc(MyStruct **, int)’ loadFunc(&tIPArray, 3);
答案 0 :(得分:2)
此声明...
MyStruct* tIPArray[3];
将tIPArray
声明为3 MyStruct *
的数组。因此,&tIPArray
是指向这样的数组的指针,其类型为MyStruct *(*)[3]
,正如错误消息所指出的那样。此类型与函数参数的预期类型MyStruct **
不同。
您可以改为将显式指针传递给第一个元素...
loadFunc(&tIPArray[0], 3);
...,但是省略&
会更加惯用,因为将数组普通转换为指针(数组的“衰减”)会生成正确类型和值的指针:
loadFunc(tIPArray, 3);
答案 1 :(得分:2)
如果使用typedef MyStruct* StrPtr;
,也许会更清楚。然后您的示例变为:
void foo(StrPtr* bar);
StrPtr array[4];
首先,让我们看看这个电话:
foo(array);
数组的类型为StrPtr[4]
,而不是StrPtr*
。理想情况下,它将调用foo(StrPtr bar[4])
,但是没有这样的功能。下一个最佳匹配是数组可以衰减为指向其元素= StrPtr*
的指针,幸运的是有foo(StrPtr* bar)
函数使调用有效。
现在,该表达式的类型是什么?
&array;
好吧,数组也是StrPtr[4]
类型的,因此它必须是指向该类型= StrPtr(*)[4]
的指针。与函数指针相同的“怪异”语法。
最后,请拨打此电话:
foo(&array);
我们现在知道这想调用foo(StrPtr(*bar)[4])
,并且再次没有这样的功能。那么编译器能做什么? &array
不是数组,它是一个指针,指针不能衰减到任何东西。嗯,现在呢?好吧,在C中,无论类型如何,任何指针都可以传递给另一个指针。取消引用此类指针是另一回事。因此,此呼叫有效,并且由于没有其他候选者而呼叫foo(StrPtr* bar)
。成功?不,任何体面的编译器都应对此进行警告,甚至最好像使用-Wincompatible-pointer-types
一样将这些警告转换为错误,甚至禁止使用-Werror
禁止所有警告。
因此,可以得出的结论是正确的呼叫是foo(array);
。