我得到“不兼容的指针类型”,我不明白为什么

时间:2015-11-15 23:00:04

标签: 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]'

似乎编译器抱怨在接受const的函数中接收非const,但我被告知这是使用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);
}

我正在寻找不使用指针的最佳解决方案,因为这是我们尚未涵盖它们的课程练习(尽管我已经研究过它们)。

2 个答案:

答案 0 :(得分:2)

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

这是语言的缺陷;没有技术原因可以解释为什么不允许这样的转换。 (C ++允许这种转换)。

你有两种选择,都没有吸引力:

  1. 让函数接受int而不是const int
  2. 在调用const int函数时写一个演员,例如printMatrix((const int (*)[MAXCOL])m, 5, 5);
  3. 通常会使用选项1,我们只需要对多维数组没有const正确性。

答案 1 :(得分:1)

<强>问题

当您在函数调用中使用m时,它会衰减为指针。 m衰为的指针类型为int (*)[5] - 指向&#34; 5 int s&#34;的数组。

鉴于fillMatrix的声明,预期的参数类型为int (*)[MAXCOL],即int (*)[80] - 指向&#34; 80的数组ints&# 34。

这两种类型不兼容。

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

为了便于说明,我将把数组的大小更改为2和4。

有关

int m1[2][2];

内存布局如下:

m1[0][0]    m1[1][1]
|           |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+

如果声明一个指针,那么

int (*p1)[2] = m1;

指针透视图的内存布局如下所示:

p1      p1+1    p1+2
|       |       |
v       v       v
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+

现在,让我们创建一个大小为4 x 4的数组,并从指针的角度检查内存布局的外观。

int m2[4][4];

内存布局:

m2[0][0]                                                    m2[3][3]
|                                                           |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

指针:

int (*p2)[4] = m1;

指针透视图的内存布局如下所示:

p2              p2+1            p2+2            p2+3            p2+3
|               |               |               |               |
v               v               v               v               v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

如果比较指针算法如何用于两种不同的指针类型,您将看到:

就执行指针之前这些指针的值如何偏移而言,

p1[1][0]完全不同p2[1][0] - &gt; int解除引用。

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

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

<强>解决方案

有很多方法可以解决这个问题。最简单的解决方案是使用

int m[2][MAXCOL];