2011-07-11 37 views
3

最近,我調試了一個程序,發現我經常犯的一個錯誤,但是在編譯期間它沒有顯示爲警告,所以我只是假設一切都是到位,並確定。我有點糊塗剛剛發生在下面的代碼:將數組的地址作爲函數參數

void foo(char b[2]); 
char a[2] = {1, 2}; 
foo(a); // I always assumed that this would pass the entire array to be 
      // duplicate in stack, guess I was wrong all this while 
      // Instead the address of the array was passed 

void foo(char b[2]) 
{ 
    // Value of b[0], b[1]? 
    // Does this mean : 1) b[0] == &a[0]? 
    //    or 2) b[0] == &a[0+2]? 
    // Compiler didn't complain, so I assume this is a valid syntax 
} 

回答

6

當傳遞數組作爲參數傳遞給它衰變爲一個指針的函數,這是在C標準定義在6.7.1

在進入函數每個參數表達式的值應轉換爲其相應參數的 類型,就像通過賦值給參數一樣。 數組表達式和 作爲參數的函數指示符在調用之前轉換爲指針。一個 參數爲「類型的數組」的聲明應調整到「指針類型,

這基本上意味着你的函數聲明是等同用

void foo(char b[2]);void foo(char b[]);void foo(char *b)

`

+0

foo的(焦B [2]),這是否意味着我會限制訪問大小爲2,例如b [0],b [1]有效,但不是b [2]等等? – freonix

+4

不,您放入括號中的實際值沒有相關性。 – lccarrasco

+2

更清楚的是,你可以用任意大小的字符組調用'f',在'f'裏面你可以訪問數組中所有有效的位置而沒有問題,但是如果你嘗試訪問超出實際大小的位置你的數組屬於你未定義的行爲,這意味着任何事情都可能發生。 – lccarrasco

0

它是有效的語法,是的,傳遞數組時,第一個元素的內存地址被複制,但是當你提領的地址,你是修改原始數組。

0

這是一樣的如下:

// The array "char b[2]" "decays" to a pointer "char *b" 
void foo(char *b) 
{ 
    // b[0] == a[0] 
    // also, b == a (two addresses, both the same) 
} 

您可以在數組和指針用C的行爲非常相似(但不完全相同相同)讀了。數組衰減爲指針,如果它們是函數參數(但不在其他地方)。這裏真正的問題是,在64位系統上,sizeof(b) == 8sizeof(a) == 2,這是有點令人驚訝,除非你知道陣列衰變成指針。

0
  1. 當你聲明一個數組作爲函數參數時,它被當作是一個指針。你foo是完全一致

    void foo(char *b) 
    { 
        ... 
    } 
    
  2. 數組衰變爲指針。換句話說,在一些用途中(例如sizeof(a)a是一個數組,但在其他地方預期有指針,名稱a意味着的地址爲a[0]

0

b[0] = &a[0]如果你做foo(a)作爲參數。

如果你通過foo((a+1))然後b[0] = &a[1](你不應該這樣做,但因爲b[1]將是未定義的)等等。

0

我應該做一個correcti on:數組的地址未被傳遞 - 它是數組第一個元素的地址。最簡單的方法是:

在C中,數組的值是指向其第一個元素的指針。

如果用數組的數組工作,你需要先提領後提供有關數組的大小信息:

// either the following or: void foo(char param[][30][20]) 
void foo(char (*param)[30][20]) 
{ 
    // ... 
} 


int main(void) 
{ 
    // bar is an array of 10 arrays of 30 arrays of 20 chars. 
    // its value's TYPE is 'pointer to an array of 30 arrays of 20 chars, 
    // which is what foo above requires. 
    char bar[10][30][20]; 

    foo(bar); 

}