【问题标题】:C Matrix Dimension Different From DeclarationC矩阵维度与声明不同
【发布时间】:2017-04-10 07:51:09
【问题描述】:

如果之前有人问过这个问题,我提前道歉——我找不到。

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

#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] 的矩阵,但是当我在另一个函数中使用此矩阵并以大小 [4][3] 调用它时,它返回了奇怪的结果。有人可以解释在这种情况下访问内存的方式吗?

【问题讨论】:

  • 你的编译器应该警告你。编译时启用所有警告。
  • 只需将函数更改为void print_matrix(int x, int y, int a[x][y])。请注意,C 不允许大小为零的数组。

标签: c matrix


【解决方案1】:

您的代码具有未定义的行为,因此任何事情都可能发生。该函数的第一个参数应该是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)

所以本质上,通过阅读arraya,您访问了错误的单元格。

【讨论】:

    猜你喜欢
    • 2022-01-01
    • 1970-01-01
    • 2017-07-02
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多