2017-04-10 126 views
2

如果之前询问过,我很抱歉 - 我无法找到它。C矩阵尺寸不同于声明

这只是一个奇怪的错误,我不明白哪些实用性很少(如果有的话)。下面是代码:

#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],则返回奇怪的结果。有人可以解释在这种情况下访问内存的方式吗?

+0

你的编译器应该警告你。编译启用所有警告。 –

+0

只需将该函数更改为void void print_matrix(int x,int y,int a [x] [y])'。请注意,C不允许大小为零的数组。 – Lundin

回答

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) 

因此,本质上,通过arraya,您访问错误的单元格。