我遇到两种错误:
编译器的投诉
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);
}
我正在寻找不使用指针的最佳解决方案,因为这是我们尚未涵盖它们的课程练习(尽管我已经研究过它们)。
答案 0 :(得分:2)
不幸的是,在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正确性。
答案 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];