簡體   English   中英

函數原型和塊代碼中的變量聲明:有區別嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM