我写了一个简单的代码,它得到了最多M行的矩阵,我无法理解为什么它会给我一个奇怪的输出:
对于M = 50:
"单元格[1] [0]是:17273520" (我每次都得到随机输出)
对于M = 4:
"单元格[1] [0]是:0" (总是)
#define M 50
void printImage(int a[][M]){
printf("the cell [1][0] is : %d",a[1][0]);
}
int main(){
int a[3][4] = {0};
printImage(a);
}
有人能解释一下M的确切含义吗?这个怎么运作 ? 如何使函数适用于少于M行的矩阵?
答案 0 :(得分:4)
C中的二维数组a
是一个数组数组。因此a
的每个成员必须具有相同的大小。定义中的第二个size参数是该大小。
传递给printImage
的是一个二维数组,它会衰减到一个指针。它指向a
的第一个数组元素。
现在,由于真正的二维数组的多维指针算术a[i][j]
是*(a + i * M + j)
,我们看到M是类型定义的一部分。
如果您指定通过a[][50]
但实际上通过了a[][4]
,那么a[1][0]
的索引将在数组范围之外 way 。
由于访问数组边界外部是未定义的行为,任何事情都可能发生,你得到一些随机值。但是程序可能会像硬盘一样崩溃或格式化。
这也是为什么你应该始终以尽可能高的警告级别构建你的程序(甚至将大部分变成硬错误)。例如,GCC can protect you具有以下有用的诊断:
错误:传递' printImage'的参数1来自不兼容的指针类型[-Wincompatible-pointer-types]
如果需要二维数组的数组元素具有不同的大小。您可以指定该函数接受variable length array。首先传递数组尺寸的大小,然后传递具有以下尺寸的数组:
void printImage(size_t n, size_t m, int a[n][m])
{
// a is a VLA with dimensions specified by n and m
// pointer arithmetic will be *(a + i * m + j)
}
答案 1 :(得分:3)
您将a
定义为数组a[3][4]
,但在printImage
中,您告诉编译器最后一个维度是50而不是4。
这样就搞乱了数组的内存映射,编译器读取了远远落后于数组的错误内存位置。
您应始终使用正确的尺寸。 这可以这样做:
int a[3][M];
在main()中。
答案 2 :(得分:0)
您已经定义了一个尺寸为3x4的矩阵,共有12个整数。但是在函数中,您已将第二个维度定义为50,这超出了实际维度。当你尝试从[1][0]
读取一个值时,它会转到位置50,这与位置11中的最后一个初始化值相差很远。这就是你得到一些随机值的原因。