[英]Variable declaration in function prototype and in block code : difference?
為什么int array[]
在main而不是在函數原型中引發編譯錯誤? 是否應該總是在函數原型中編寫int * array
更好?
void myfoo (int array[]) { // No compilation error
;}
void myfoo1 (int *array1) { // No compilation error
;}
int main() {
int array[]; // Compilation error
int* array1; // No compilation error
}
在函數內部的代碼中,編寫int array[];
因為數組定義是語義錯誤。
在這種情況下, array
是一個沒有鏈接的變量( “沒有存儲類說明符extern
聲明的對象的塊作用域標識符” ),並且按照規范:
如果聲明的對象標識符沒有鏈接,則對象的類型應在其聲明符[....]的末尾完成。
空的[]
(之間有空格,也沒有空格),不能為數組定義建立有效的構造,因為數組的大小仍然未知(請注意,也缺少明確的用括號括起來的初始化列表) )。 因此,您的編譯器會抱怨,因為類型不完整,並且不知道要為該數組變量保留的內存總量。
另一方面,對於函數參數,數組類型參數實際上會衰減為指向該類型的指針,因此,指定數組大小不是強制性的。 引用第6.7.6.3節
參數聲明為“類型數組”應調整為“類型的合格指針”,其中類型限定符(如果有)是在數組類型派生的[和]中指定的那些。 [...]
和
如果函數聲明符不是該函數定義的一部分,則參數可能具有不完整的類型,並可能在其聲明符說明符的序列中使用
[*]
表示法來指定可變長度數組類型。
所以,基本上,一個聲明
void myfoo (int array[])
等價於
void myfoo (int *array)
因此,這被編譯器接受。
從根本上說,其原因為塊內的數組宣言main
需要的尺寸和在函數參數數組聲明不是,在聲明main
是定義的陣列,而函數參數僅僅接收陣列別的限定。
因此main
的定義需要一個大小,因為它必須為數組保留存儲空間。
函數參數僅接收數組,因此只需要知道數組從哪里開始。 它不需要知道大小。 (也就是說,編譯器不需要知道大小即可編譯代碼。函數可能需要知道大小即可執行其預期目的,但這對程序員而言是問題,而不是編譯器。)
由於C規則,數組實際上永遠不能作為函數參數傳遞。 只要將數組作為函數參數給出,編譯器就會自動將其轉換為指向其第一個元素的指針。 同樣,函數參數可以是指針,但實際上不能是數組。 當您將函數參數聲明為數組時,編譯器會自動對其進行調整以聲明一個指針。 因此,函數聲明void myfoo(int array[])
會自動調整為void myfoo(int *array)
。
需要在main
聲明大小的特定規則是C 2018 6.7 7:
如果聲明的對象標識符沒有鏈接,則該對象的類型應在其聲明器的末尾,或者在它具有初始化程序的init聲明器的末尾完成;…
void myfoo (int array[]) { // No compilation error
;}
這意味着myfoo()將被一個整數數組(任意大小)調用。 編譯器可以編譯它。
void myfoo1 (int *array1) { // No compilation error
;}
這意味着將使用指向整數的指針來調用myfoo1()。 編譯器可以編譯它。
int main() {
int array[]; // Compilation error
int* array1; // No compilation error
}
int array[];
這是數組的定義。 但是編譯器無法確定數組的大小。 因此它不知道要分配多少內存。 因此,您必須提供size或使用以下一些值對其進行初始化。
int array[3];
要么
int array[] = {1,2,1};
。
int* array1;
這只是整數指針的聲明。 它沒有任何問題,編譯器可以對其進行編譯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.