如果之前有人问我,我会提前道歉 - 我找不到它。
这只是一个奇怪的错误,我不明白它有什么实用性(如果有的话)。这是代码:
#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]调用它时,它会返回奇怪的结果。有人可以解释在这种情况下访问内存的方式吗?
答案 0 :(得分:2)
您的代码具有未定义的行为,因此任何事情都可能发生。函数的第一个参数应该是int (*a)[3]
,指向3个整数数组的指针。作为函数参数的数组总是衰减到指针,在这种情况下是指向数组的指针。但是当你传递array
时,它会衰减到int(*)[5]
,这是一个指向5个整数数组的指针。
根据C11标准的以下小节:
要使两个指针类型兼容,两者都应具有相同的限定条件,并且两者都应是兼容类型的指针。
对于两个要兼容的数组类型,两者都应具有兼容的元素类型,如果两个大小说明符都存在,并且是整数常量表达式,则两个大小说明符应具有相同的常量值。如果在要求它们兼容的上下文中使用这两种数组类型,则如果两个大小说明符计算为不相等的值,则它是未定义的行为。
由于指针类型不兼容,因此允许编译器发出它想要的任何代码,没有任何限制。代码甚至没有意义,这就是未定义行为的含义。
但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
,您可以访问错误的单元格。