簡體   English   中英

函數聲明與函數定義

[英]Function declaration vs function definition

如果我有這個原型:

int bar(int);

對於編譯器,我聲明了標識符bar

如果我有這個定義:

int bar(int a) {};

對於編譯器,我定義了標識符bar

一般來說,定義為對象進行存儲分配,但是:

  1. 函數聲明也是如此嗎? 同樣在這種情況下沒有分配存儲空間?
  2. 為函數定義分配的存儲空間是多少?何時分配?

PS C 規范在談到聲明或定義時說的是他們相對的標識符(即標識符的聲明......)但我也讀過文本,其中說的是變量聲明 那么有什么區別還是只有一種含義的“雙重方式”?

函數聲明有助於編譯器檢查您對函數的調用是否遵循相同的簽名,以確保在返回類型、參數數量和類型以及參數順序方面的語法正確性。 鏈接器需要一個函數定義來交叉引用調用(使用)和定義。

當你聲明一個函數時,沒有分配存儲空間,當你定義一個函數時,在可重定位的可重載地址空間上創建的函數,大小取決於函數的機​​器語言翻譯,因平台而異

在函數的情況下,存儲分配在函數第一次調用時完成。 定義本身不進行存儲分配。

您還應該注意,當函數的返回類型為void時,使函數體為空是有效的。 因此,編譯器應該針對

int bar(int a) {};  

[警告] 控制到達非空函數的結尾 [-Wreturn-type]
[警告] ISO C 不允許額外的 ';' 在函數之外 [-pedantic]

在C標准中,每一個定義也是一個聲明,一個函數不是一個對象(我這里只是提一下,因為很多人使用不同的術語,我不確定你使用哪種約定,我將使用術語標准,因為這在 SO 上很常見)。

對於標准(即在抽象機中),函數不占用存儲空間。 術語“定義”在 C11 (n1570) 6.7 p5 中定義

聲明指定了一組標識符的解釋和屬性。 標識符的定義是對該標識符的聲明: - 對於一個對象,導致為該對象保留存儲; - 對於函數,包括函數體; *) - 對於枚舉常量,是標識符的(唯一)聲明; - 對於 typedef 名稱,是標識符的第一個(或唯一)聲明。 [與不允許重新定義 typedef 的 C99 略有不同]

*)函數定義具有不同的語法,如 6.9.1 所述。

該標准僅在腳注等非規范部分使用術語“變量”(作為名詞;它在規范部分用作形容詞,如“可變長度數組”)。

關於“標識符”一詞,見同上。 6.4.2.1,

(2) 標識符是由非數字字符(包括下划線_ 、小寫和大寫拉丁字母以及其他字符)和數字組成的序列,它指定一個或多個實體,如 6.2.1 所述。

同上。 6.2.1 p1

標識符可以表示一個對象; 一個函數; 結構、聯合或枚舉的標記或成員; 一個typedef名稱; 標簽名稱; 宏名稱; 或宏參數。 相同的標識符可以表示程序中不同點的不同實體。 枚舉的成員稱為枚舉常量。 此處不再進一步考慮宏名稱和宏參數,因為在程序翻譯的語義階段之前,源文件中出現的任何宏名稱都被構成它們的宏定義的預處理標記序列替換。

為了完整起見,函數原型是一個聲明; 舊式聲明和舊式定義是非原型聲明。

在 C 和 C++ 中聲明某些東西意味着什么

當你聲明一個變量、一個函數,甚至一個類時,你所做的只是在說:有一個叫這個名字的東西,它有這個類型。 然后編譯器可以處理該名稱的大部分(但不是全部)使用,而無需該名稱的完整定義。 聲明一個值——而不定義它——允許您編寫編譯器可以理解的代碼,而不必放置所有細節。 如果您正在處理多個源文件,並且需要在多個文件中使用一個函數,這將特別有用。 您不想將函數體放在多個文件中,但確實需要為其提供聲明。

那么聲明是什么樣的呢? 例如,如果你寫:

int func();

這是一個函數聲明; 它不提供函數的主體,但它確實告訴編譯器它可以使用這個函數並期望它將在某處定義。

在 C 和 C++ 中定義某些東西意味着什么

定義某物意味着提供所有必要的信息來完整地創建該事物。 定義一個函數就是提供一個函數體; 定義一個類意味着給出該類的所有方法和字段。 一旦定義了某事,也算作聲明; 所以你經常可以同時聲明和定義一個函數、類或變量。 但你沒有必要。

例如,對於編譯器來說,有一個聲明通常就足夠了。 你可以這樣寫代碼:

int func();

int main()
{
 int x = func();
 }

int func()
 {
 return 2;
 }

由於編譯器知道 func 的返回值,以及它需要的參數數量,它可以編譯對 func 的調用,即使它還沒有定義。 實際上,func 方法的定義可以放到另一個文件中!

你也可以聲明一個類而不定義它

類 MyClass;

需要知道 MyClass 中內容的詳細信息的代碼無法工作——你不能這樣做:

class MyClass;

MyClass an_object;

 class MyClass 
 {
 int _a_field;
 };

因為編譯器需要知道變量 an_object 的大小,而從 MyClass 的聲明中無法做到; 它需要下面顯示的定義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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