2010-07-16 198 views
4

我的問題是:當我寫一個函數原型用C這樣的:參數函數原型

void foo(int *vector); 

這是應該做同樣的事情:

void foo(int vector[MAX_LENGTH]); 

的功能,傳遞總是作爲一個指針?代碼是一樣的? 在此先感謝。

回答

1

有沒有其他的東西可以通過!但[]限制讓編譯器可以做更多的檢查。

+0

大多數C編譯器實際上不會執行這些檢查。 – nmichaels 2010-07-16 12:07:53

+0

實際上,任何編譯器都會試圖根據函數參數上的'[]'中指定的邊界來檢查數組長度是不符合的。標準非常明確 - '[]'只是變成了'*' - 所以像'void foo(int a [2]){a [0] ++; } ... int x; foo(&x);''有一個明確的含義,並且一個編譯器會插入任何支票,在那裏沒有按照規範 – 2010-07-16 20:24:16

+0

插入支票嗎?我說_do_支票,意思是在編譯時! 對不起,有些混淆 – vlabrecque 2010-07-16 23:45:11

6

是的,數組類型在傳遞給函數時會隱式轉換爲指針類型。

所以

void foo(int *a)void foo(int a[])是相同的。

可以輕鬆地檢查,使用sizeof()操作功能定義

例如

void foo(int a[]) 
{ 
    std::cout<<sizeof(a); //prints sizeof(int*) 
} 

int main() 
{ 

    int a[]={1,2,3,4}; 
    foo(a); 
} 

EXTRA(打印的陣列的在函數內部尺寸)

[C++ Only]

內部
template<typename T,size_t n> 
void size_of_array(T (&a)[n]) //Array passed by reference. Template argument deduction 
{ 
    std::cout<<sizeof(a); //prints sizeof(n*sizeof(int)) 
} 

int main() 
{ 
     int a[]={1,2,3,4,5}; 
     size_of_array(a); 
} 
+2

+ 1用於指出sizeof是技巧性的 – nmichaels 2010-07-16 12:27:10

+0

對於C++來說,更好的方法來演示這個是用'puts(typeid(a).name())' – 2010-07-16 20:24:58

8

這是微妙的。 C中的數組不是指針,但C不允許將數組作爲函數參數傳遞。所以當你有void foo(int vector[MAX_LENGTH]);時,基本上你所做的只是告訴其他程序員(以及你未來的自己),這個函數需要傳遞一個MAX_LENGTH數組給它。編譯器不會幫助你。它會默默地將你的數組轉換爲一個指針。

This解釋得很好。

+0

+1來表示重新訪問代碼 – 2010-07-16 12:10:51

2

這是C語言的粗糙邊緣之一。兩個聲明看起來完全相同(但名稱相同),原型中的一個和堆棧變量中的一個聲明導致聲明兩種不同類型的變量。

void foo(int A[10]) { 
    int B[10];  
} 

內部的foo範圍,A指針爲intB陣列int類型的10個元素。正如其他人提到的,即使他們的尺寸與sizeof計算是不同的。

C++繼承了該規則,因此對於您的示例代碼,兩個函數的原型應該是相同的。

C99此事通過引入新的關鍵字static ;-)

void foo(int A[static 10]) { 
    int B[10];  
} 

這並不能改變如何AB規則從內部被視爲進一步複雜化,而是提供了一個信息給預期有多少數組元素的調用者方。目前gcc接受這個新的語法,並簡單地忽略這個信息。

+1

如果我沒有記錯的話,唯一與「static」的不同之處在於,調用者將指針傳遞給數組較少的數組即可,即使該函數實際上並未嘗試對其進行解引用 - 它可以讓編譯器如果它看到該數組在函數中沒有發生變異,並且不可能通過一個a變量來將它實現爲小尺寸數組的傳遞值裏阿斯。 – 2010-07-16 20:22:17

+0

@Pavel:我檢查了規範,它看起來是必要的,而不是U.B.,它們應用動詞*必須*和*必須*。在gcc文檔中他們表示這是他們仍然不符合C99標準的其中一點。我也不認爲這允許通過值,因爲它允許將指針傳遞給大於指定的數組。 – 2010-07-18 06:37:34

+0

「如果一個」應該「或」不得「違反約束條件的要求被違反,那麼這個行爲就是未定義的。本標準中未定義的行爲以'未定義行爲'或通過省略任何明確的行爲定義,這三者之間的重點沒有區別,它們都描述了「未定義的行爲」。 – 2010-07-18 17:25:59