C I';“我得到了”;不兼容的指针类型“;我不知道';我不明白为什么

C I';“我得到了”;不兼容的指针类型“;我不知道';我不明白为什么,c,pointers,C,Pointers,我得到两种类型的错误: 编辑投诉 pr.c:在函数“main”中: pr.c:20:2:警告:从不兼容传递“printMatrix”的参数1 指针类型[默认情况下启用] pr.c:9:6:注意:应为'const int(*)[80]”,但参数的类型为'int(*)[80]' pr.c:22:2:警告:从不兼容的指针类型传递'lights'的参数1[默认启用] pr.c:10:6:注意:应为'const int(*)[80]”,但参数的类型为'int(*)[80]' 编译器似乎抱怨在一个接受常量的

我得到两种类型的错误:

编辑投诉

pr.c:在函数“main”中:

pr.c:20:2:警告:从不兼容传递“printMatrix”的参数1 指针类型[默认情况下启用]

pr.c:9:6:注意:应为'const int(*)[80]”,但参数的类型为'int(*)[80]'

pr.c:22:2:警告:从不兼容的指针类型传递'lights'的参数1[默认启用]

pr.c:10:6:注意:应为'const int(*)[80]”,但参数的类型为'int(*)[80]'

编译器似乎抱怨在一个接受常量的函数中接收非常量,但我被告知这是使用
const
的正确方法

#include <stdio.h>
#include <stdlib.h>

#define MAXCOL  80
#define MAXROW  20
#define randNormalize() srand(time(0))

void fillMatrix(int m[][MAXCOL], size_t rows, size_t cols);
void printMatrix(const int m[][MAXCOL], size_t rows, size_t cols);
void lights(const int m[][MAXCOL], size_t rows, size_t cols);
int star(const int m[][MAXCOL], int row, int col);

int main()
{
    int m[MAXROW][MAXCOL];

    randNormalize();

    fillMatrix(m, 5, 5);
    printMatrix(m, 5, 5);

    lights(m, 5, 5);

    return 0;
}

void fillMatrix(int m[][MAXCOL], size_t rows, size_t cols)
{
    int i, j;

    for(i = 0; i < rows; i++)
        for(j = 0; j < cols; j++)
            m[i][j] = rand()%21;

}

void printMatrix(const int m[][MAXCOL], size_t rows, size_t cols)
{
    int i, j;

    for(i = 0; i < rows; i++)
    {
        printf("\n");

        for(j = 0; j < cols; j++)
            printf("%d ", m[i][j]);
    }

    printf("\n");
}


void lights(const int m[][MAXCOL], size_t rows, size_t cols)
{
    int i, j;

    for(i = 1; i < rows - 1; i++)
    {
        printf("\n");

        for(j = 1; j < cols - 1; j++)
        {
            if( star(m, i, j) )
                printf("*");
            else
                printf(" ");
        }
    }

    printf("\n");
}



int star(const int m[][MAXCOL], int row, int col)
{
    int i, j;
    int sum = 0;

    for(i = row - 1; i <= row + 1; i++)
        for(j = col - 1 ; j <= col + 1; j++ )
            sum += m[i][j];

    return (sum/9 > 10);
}
#包括
#包括
#定义MAXCOL 80
#定义MAXROW 20
#定义randNormalize()srand(时间(0))
空填充矩阵(int m[][MAXCOL],大小行,大小列);
无效打印矩阵(常量int m[][MAXCOL],大小行,大小列);
空心灯(常数m[][MAXCOL],大小行,大小列);
整数星型(常数整数m[][MAXCOL],整数行,整数列);
int main()
{
int m[MAXROW][MAXCOL];
randNormalize();
填充矩阵(m,5,5);
打印矩阵(m,5,5);
灯光(m、5、5);
返回0;
}
空填充矩阵(int m[][MAXCOL],大小行,大小列)
{
int i,j;
对于(i=0;i对于(i=第1行;i问题

在函数调用中使用
m
时,它会衰减为指针。
m
衰减为的指针类型是
int(*)[5]
——指向“5个
int
s数组”的指针

给定
fillMatrix
的声明,预期的参数类型是
int(*)[MAXCOL]
,即
int(*)[80]
——指向“80个
int的数组
”的指针

这两种类型不兼容

这两种类型不兼容的原因可以通过查看编译器期望指针的行为以及期望的内存布局来理解

为了便于解释,我将把数组的大小改为2和4

为了

内存布局如下所示:

m1[0][0]    m1[1][1]
|           |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p1      p1+1    p1+2
|       |       |
v       v       v
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p2              p2+1            p2+2            p2+3            p2+3
|               |               |               |               |
v               v               v               v               v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
如果声明一个指向该数组的指针

int (*p1)[2] = m1;
指针透视图中的内存布局如下所示:

m1[0][0]    m1[1][1]
|           |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p1      p1+1    p1+2
|       |       |
v       v       v
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p2              p2+1            p2+2            p2+3            p2+3
|               |               |               |               |
v               v               v               v               v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
现在,让我们创建一个大小为4x4的数组,并从指针的角度检查内存布局的外观

int m2[4][4];
内存布局:

m2[0][0]                                                    m2[3][3]
|                                                           |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
指针:

int (*p2)[4] = m1;
指针透视图中的内存布局如下所示:

m1[0][0]    m1[1][1]
|           |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p1      p1+1    p1+2
|       |       |
v       v       v
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
p2              p2+1            p2+2            p2+3            p2+3
|               |               |               |               |
v               v               v               v               v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
如果比较指针算法如何用于两种不同的指针类型,您将看到:

p1[1][0]
在执行指针->
int
解引用之前,这些指针的值是如何偏移的,这与
p2[1][0]
大不相同

如果将
p1
视为与
p2
的类型相同,指针算法将很容易导致访问数组超出范围,并导致未定义的行为

这就是为什么当预期的参数类型为
int(*)[80]
时,编译器不会使用
int(*)[4]
类型的指针

解决方案

解决这个问题的方法有很多,最简单的方法是使用

int m[2][MAXCOL];

不幸的是,在C语言中没有从
int[X][Y]
const int[X][Y]
的隐式转换,也没有从
int(*)[Y]
const int(*)[Y]
的隐式转换

这是语言中的一个缺陷;不允许这种转换没有任何技术原因。(C++允许这种转换)

您有两个选项,都没有吸引力:

  • 让函数接受
    int
    而不是
    const int
  • 调用
    const int
    函数时编写强制转换,例如
    printMatrix((const int(*)[MAXCOL])m,5,5);

  • 通常会使用选项
    1
    ,我们只需对多维数组不使用const正确性即可。

    const
    -这很好,但是
    fillMatrix
    需要一个指向80
    int
    s数组的指针,而您传递一个指向5数组的指针。这是不兼容的。可能会解释更多。为什么c好吗?我想把它处理掉:~(.仅供参考,这些消息不是两个独立的警告。它们是同一警告的一部分。为什么呢?它们是关于不同行的消息。哦,好的,我现在看到你已经为两个警告提供了一半的消息。我的意思是,每个警告都应该告诉你警告类型,然后是警告注释。这是你分别显示的,但用于不同的警告行。因此,您实际上应该发布警告输出中的所有4行,或者至少为每行发布一致的警告消息的相同部分。感谢您的完整解释!我需要花一点时间才能理解所有内容。注意:此答案指的是问题的修订版1;它没有解决
    常量不兼容。关于选项2,cast应具有参数的类型,即
    printMatrix((const int(*)[MAXCOL])m,5,5)