有人可以解释这种行为吗?

时间:2017-01-08 16:24:11

标签: c

我写了一个简单的代码,它得到了最多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行的矩阵?

3 个答案:

答案 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) 
}

The above is valid C99

答案 1 :(得分:3)

您将a定义为数组a[3][4],但在printImage中,您告诉编译器最后一个维度是50而不是4。 这样就搞乱了数组的内存映射,编译器读取了远远落后于数组的错误内存位置。

您应始终使用正确的尺寸。 这可以这样做:

 int a[3][M]; 

在main()中。

答案 2 :(得分:0)

您已经定义了一个尺寸为3x4的矩阵,共有12个整数。但是在函数中,您已将第二个维度定义为50,这超出了实际维度。当你尝试从[1][0]读取一个值时,它会转到位置50,这与位置11中的最后一个初始化值相差很远。这就是你得到一些随机值的原因。