2017-04-10 249 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,您訪問錯誤的單元格。