C 不兼容的参数类型?
我想使用另一个函数来打印数组的内容。 当我运行代码时,我得到“IntelliSense:类型为“int(*)[3][3]”的参数与类型为“int*(*)[3]”的参数不兼容 这是我的职责:C 不兼容的参数类型?,c,arrays,function,C,Arrays,Function,我想使用另一个函数来打印数组的内容。 当我运行代码时,我得到“IntelliSense:类型为“int(*)[3][3]”的参数与类型为“int*(*)[3]”的参数不兼容 这是我的职责: void display(int *p[N_ROWS][N_COLS]) { int i, j; for (i = 0; i < N_ROWS; i++) { for (j = 0; j <N _COLS; j++) { printf("%i
void display(int *p[N_ROWS][N_COLS]) {
int i, j;
for (i = 0; i < N_ROWS; i++) {
for (j = 0; j <N _COLS; j++) {
printf("%i", p[i][j]);
}
}
}
我的两个参数不是都是int(*)[3][3]
类型,还是我遗漏了什么
在对您的问题的评论中已经解释了其中的大部分内容
您对显示的定义
:
void display(int*p[N_ROWS][N_COLS])
{
int Array [N_ROWS][N_COLS] = { {1,2,3},{4,5,6},{7,8,9} };
display(&Array);
这表示p
将是指向int
的指针的数组N行
调用显示时
:
void display(int*p[N_ROWS][N_COLS])
{
int Array [N_ROWS][N_COLS] = { {1,2,3},{4,5,6},{7,8,9} };
display(&Array);
您正在传入数组的地址
,因此它是指向int
的数组N行
的指针
要使显示的定义与您调用它的方式匹配,请执行以下操作:
void display(int (*p)[N_ROWS][N_COLS])
{
括号使*
首先与p
关联。由于p
是指向int
数组的指针,因此要到达int
需要额外的解引用:
printf("%i\n", (*p)[i][j]);
定义display
以获取指向数组的指针意味着数组的大小绑定到类型参数,因此display
确切地知道数组的尺寸
另一种方法是定义display
,将数组的维度作为第二个参数
void display(int p[][N_COLS], int n_rows)
{
在这种情况下,p
参数是指向int
的数组N_COLS
的指针。在大多数表达式中使用T数组时,T数组将衰减为指向T的指针类型的值,该值等于其第一个元素的地址。因此,您可以这样调用第二个版本的display
:
int Array [N_ROWS][N_COLS] = { {1,2,3},{4,5,6},{7,8,9} };
display(Array, N_ROWS);
第二种方法的优点是display
可以处理行数少于或多于N_行的数组。缺点是由调用方传递正确的行数
您可能认为以下声明将为您提供完整的类型安全性:
void display(int p[N_ROWS][N_COLS])
{
但是,C中用于函数参数的数组语法会导致忽略p
的大小信息,并将其等效于int p[][N_COLS]
,然后将其视为int(*p)[N_COLS]
您的显示的原型以及调用语法都不正确:您定义display
以获取指向int
的二维指针数组,而如果int
,则只需要一个二维数组,当您在main
中传递指向数组的指针时,指针将作为一个点衰减这是它的第一个元素
以下是一个更简单的版本:
void display(int p[N_ROWS][N_COLS]) {
int i, j;
for (i = 0; i < N_ROWS; i++) {
for (j = 0; j < N_COLS; j++) {
printf("%i", p[i][j]);
}
}
}
您的意思可能是函数参数为int(*p)[N_行][N_列]
您的函数被声明为接受一个指针数组,而您正在向它传递一个指向数组的指针。@M.M:我怀疑OP应该从p
中删除*
。请查看数组的声明和函数参数p
。然后思考您传递给p
的内容。(但请注意语义不同)。数组不是指针(反之亦然)。请从函数中删除*
,并从调用中删除&
。@user3386109:这将破坏类型检查,并允许调用代码传递,例如int[1][3]
array作为参数。如果数组大小始终相同,即在编译时固定不变,则最好通过执行上述操作来强制调整大小,即传递指向整个数组的指针。@user3386109:C99 specificstatic
在这种情况下,数组大小中的关键字不强制任何内容。它可以作为编译器的提示,b它不触发编译时大小检查。如果你认为这个语法是“复杂的”,你可以通过使用一个中间的<代码> TyPufF数组来大大简化它。
然后声明A*
参数。@jxr:正如AnT所指出的,您的方法确实改进了类型检查,但您还必须更正OP的代码并使用printf(“%i”,(*p)[i][j])
@user3386109使用static
关键字不强制执行约束。它帮助编译器优化,编译器可以发出警告;但是标准要求编译器在任何情况下都编译代码,实际上我所知的编译器都不会发出警告。@chqrlie:一个好的compiler会就printf
使用错误发出警告。在原型中忽略N_行有什么具体原因吗?这是我唯一感到困惑的地方。@vvid:编译器根本不使用指定为函数参数的数组的大小信息,既不用于类型检查,也不用于sizeof()
,因为数组是作为指向其第一个元素的指针传递的,并且大小不被视为类型的一部分。这是出于历史原因而被接受的:C的发明者没有想到这会变得误导和容易出错。相反,他们一定认为这是程序员告诉下一位代码读者w的好方法对于数组来说,它的大小是预期的,它本身作为指针指向它的第一个元素。@ VVID来解释为什么<代码> nyReals被忽略,注意JXH建议的替代解决方案意味着<代码> NyReals不再被忽略,所以如果你想它是重要的,你可以考虑这个方法。将数组放在sizeof()
中,大小信息不会被忽略。但是,C定义了数组语义,主要允许它们“通过引用”进行处理“因此,将数组传递给函数不会导致大量数据被推送到堆栈上。他们的方法是定义数组语义,使其衰减为指针类型,函数使用的就是这种衰减的类型。因此,函数参数看起来像数组,但实际上是指针类型。”