C矩阵尺寸与声明不同

时间:2017-04-10 07:51:10

标签: c matrix

如果之前有人问我,我会提前道歉 - 我找不到它。

这只是一个奇怪的错误,我不明白它有什么实用性(如果有的话)。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void print_matrix(int a[4][3], int i, int j)
{
    printf("a[%d][%d] = %d\n", i, j, a[i][j]);
    return;
}

int main(void)
{
    int i, j;
    int array[3][5];
    for (i = 0; i < 3; i++)
    {
        for(j = 0; j < 5; j++)
        {
            scanf("%d",&(array[i][j]));
        }
    }
    printf("array[2][1] = %d\n", array[2][1]);
    print_matrix(array, 2, 1);
    printf("array[0][4] = %d\n", array[0][4]);
    print_matrix(array, 0, 4);
    return 0;
}

我声明了一个大小为[3] [5]的矩阵,但是当我在另一个函数中使用这个矩阵并用size [4] [3]调用它时,它会返回奇怪的结果。有人可以解释在这种情况下访问内存的方式吗?

1 个答案:

答案 0 :(得分:2)

您的代码具有未定义的行为,因此任何事情都可能发生。函数的第一个参数应该是int (*a)[3],指向3个整数数组的指针。作为函数参数的数组总是衰减到指针,在这种情况下是指向数组的指针。但是当你传递array时,它会衰减到int(*)[5],这是一个指向5个整数数组的指针。

根据C11标准的以下小节:

[§6.7.6.1 ¶2]

  

要使两个指针类型兼容,两者都应具有相同的限定条件,并且两者都应是兼容类型的指针。

[§6.7.6.2 ¶6]

  

对于两个要兼容的数组类型,两者都应具有兼容的元素类型,如果两个大小说明符都存在,并且是整数常量表达式,则两个大小说明符应具有相同的常量值。如果在要求它们兼容的上下文中使用这两种数组类型,则如果两个大小说明符计算为不相等的值,则它是未定义的行为。

由于指针类型不兼容,因此允许编译器发出它想要的任何代码,没有任何限制。代码甚至没有意义,这就是未定义行为的含义。

但GCC(以及其他编译器肯定)可以为代码发出以下警告:

warning: passing argument 1 of 'print_matrix' from incompatible pointer type [-Wincompatible-pointer-types]

所以总是在启用警告的情况下进行编译,并注意它们!

至于最有可能发生的事情,您需要考虑多维数组如何进行数组访问。大小3是数组定义的一部分,因此当您编写a[i][j]时,它将被解释为:

*(a + i * 3 + j)

但这不是array的正确算法,正确的访问等同于

*(array + i * 5 + j)

因此,从本质上讲,通过array阅读a,您可以访问错误的单元格。