【问题标题】:I'm getting "incompatible pointer type" and I don't understand why我得到“不兼容的指针类型”,我不明白为什么
【发布时间】:2015-11-15 23:00:03
【问题描述】:

我遇到两种类型的错误:

编译器的抱怨

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);
}

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

【问题讨论】:

  • const-thing 很好,但 fillMatrix 需要一个指向 80 数组 ints 的指针,而您传递一个指向 5 数组的指针。这些不兼容。 This question 可能会解释更多。
  • 为什么 const 没问题?我想摆脱它:~(。
  • 仅供参考,这些消息不是两个单独的警告。它们是同一警告的一部分。
  • 怎么回事?它们是关于不同行的消息。
  • 哦,好的,我现在看到您为两个警告提供了一半的消息。我的意思是每个警告都应该告诉你警告类型,然后是警告说明。这是您分别显示的内容,但针对不同的警告行。因此,您实际上应该发布警告输出中的所有 4 行,或者至少为每行发布一致的警告消息的相同部分。

标签: c pointers


【解决方案1】:

不幸的是,在 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);

通常会使用1 选项,我们只需要对多维数组不使用 const-correctness。

【讨论】:

  • 关于选项 2,演员表应具有参数的类型,即。 e. printMatrix((const int (*)[MAXCOL])m, 5, 5).
【解决方案2】:

问题

当你像你一样在函数调用中使用m 时,它会衰减为一个指针。 m 衰减到的指针类型是 int (*)[5] -- 指向“5 个 ints 的数组”的指针。

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

这两种类型不兼容。

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

为了解释,我将数组的大小更改为 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] 在执行指针之前如何偏移这些指针的值方面完全不同 -> int 取消引用。

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

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

解决方案

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

int m[2][MAXCOL];

【讨论】:

  • 感谢您的完整解释!我需要一点时间才能理解一切。
  • 注意:这个答案是指问题的修订版1;它没有解决const 的不兼容问题。
猜你喜欢
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
相关资源
最近更新 更多