使用函数填充二维数组时如何修复不兼容的指针类型

How to fix incompatible pointer types when using a function to fill a two dimensional array

提问人:Someone Someone 提问时间:11/9/2023 更新时间:11/10/2023 访问量:77

问:

我正在尝试编写一个函数来填充函数调用中未定义大小的二维数组,但 vsc 抱怨指针类型不兼容

#include <stdio.h>
#include <string.h>

#define ROW1 20
#define ROWNUM1 20
#define ROW2 20
#define ROWNUM2 20

int max( int x, int y){

    if(x > y) return x;
    else return y;
}

int getMatrix(int (*matrix)[]){
    return 1; //don't mind this, a placeholder
}

int main(){
    int matrix1[ROWNUM1][ROW1], matrix2[ROWNUM2][ROW2];
    int rowLen1, rowLen2;

    printf("%d", getMatrix(matrix1));
    rowLen2 = getMatrix(matrix2);

    return 0;
}

我在 vsc 问题选项卡中得到这个,但代码在没有 comlaint 的情况下运行 “从不兼容的指针类型 [-Wincompatible-pointer-types] 传递'getMatrix' 的参数 1”。感谢您提前解决此问题的任何和所有建议

数组 C 多维数组

评论

3赞 user3386109 11/9/2023
尝试添加到函数中,看看编译器对此有何看法。printf("%d\n", matrix[2][3]);getMatrix
0赞 Eric Postpischil 11/9/2023
@user3386109:这不是问题的原因,也不是用工作代码填充函数的障碍。例如,将针对此问题提供的存根 OP(对于最小可重现示例来说是正确的)替换为以开头的代码将提供可用的指针。int (*NewPointer)[DefinedSize] = matrix;
1赞 chux - Reinstate Monica 11/9/2023
@Someone 有人对定义使用不同的值会使问题更具说明性。
1赞 Lundin 11/9/2023
在这种情况下,显而易见的解决方法是 .也许有一天 MSVC 会将编译器更新到 1989 年或更晚的标准,但与此同时,您可以使用此修复程序。int getMatrix(int matrix[ROWNUM1][ROW1])

答:

4赞 Eric Postpischil 11/9/2023 #1

这是 MSVC 中的一个缺陷。MSVC 不是符合标准的 C 编译器。

int (*matrix)[]声明为指向未知数 的数组的指针。我怀疑 MSVC 可能在内部将其作为零元素数组进行处理。matrixint

在 中,数组会自动转换为指向其第一个元素的指针,因此函数的参数是指向 (20) 数组的指针。getMatrix(matrix1)matrix1ROW1intint

根据 C 标准,指向未知数数组的指针和指向数组的指针是兼容的类型,因此编译器应该接受这一点。根据 C 2018 6.7.6.1 2,如果两个指针类型具有相同的限定条件并指向兼容类型,则它们是兼容的。根据 6.7.6.2 6,如果两个数组类型都指定了其大小,则它们具有相同的大小,则它们是兼容的,但如果一个或两个数组类型都未指定其大小,则不需要。然后,仅当数组类型的元素类型兼容时,数组类型才兼容。intROW1int

如果 MSVC 的诊断只是一个警告,则这本身并不是不符合 C 标准,因为该标准允许编译器发出超出标准要求的警告。但是,断言指针类型不兼容是错误的。

上面,我注意到我怀疑 MSVC 可能将参数视为指向零元素数组的指针。这是因为使用 MSVC 19.37 进行测试会生成不同的警告消息,该消息提及为类型。您可能正在使用具有不同消息的不同版本的 MSVC,但也将大小视为零,这将解释有关不兼容类型的消息,因为零元素数组与 20 个元素的数组不兼容(尽管零元素数组是与 C 标准的另一个冲突)。int (*)[0]

测试似乎表明 MSVC 19.37(编译器资源管理器上的最新版本)不支持可变长度数组,即使使用 ,因此解决此问题的选项可能会受到限制。您可以将参数声明为 ,然后将其分配给 并自行进行地址计算,如 。(这给 C 标准带来了额外的迂腐复杂性,但我希望它在 MSVC 中起作用。/std:c17void *int *pp[row * RowLength + column]

评论

0赞 Someone Someone 11/9/2023
所以这没什么大不了的,只是 msvc 抱怨那些对符合 C 标准规则的编译器来说不是问题的事情?
0赞 SmellyCat 11/10/2023 #2

除了 Eric 的建议之外,您还可以对函数进行模板化并采用固定长度的数组。

template<int cols, int rows>
int getMatrix(int matrix[cols][rows]){
    return 1; //don't mind this, a placeholder
}

template<int rows>
int getMatrix(int *matrix[rows]){
    return 1; //don't mind this, a placeholder
}

如果编译器无法推断模板参数,请显式添加它们,例如 .getMatrix<ROWNUM2, ROW2>(matrix2)