2013-04-05 85 views
0

高級語言如javascript不給程序員 選擇爲變量的存儲位置。但是C呢。我的問題是: 是否有任何指引,在哪裏存儲變量,如大小,使用相依 等哪種存儲位置來使用變量存儲

據我瞭解,有存儲使用 數據(不包括代碼段三種可能的位置實際的代碼):

  1. 數據段
  2. 堆棧

所以瞬時小數據項應該存儲在堆棧上?

那些必須在函數之間共享的數據項呢?這些 項目可以存儲在堆或數據段中。你如何 決定選擇哪一個?

+5

C通常不會給你這些選擇,你可能會假設一些編譯器特定的擴展。最重要的工具是範圍;所有可以是當地的都應該是本地的。 – unwind 2013-04-05 14:36:49

+0

C不會讓你指定變量去的地方。沒有編譯器會。 所有本地變量都將在堆棧中,所有文字將以DATA結尾。 – Shark 2013-04-05 14:36:58

+1

全局變量通常以DATA/BSS部分結尾,除非您另行指定使用編譯器特定的擴展名。 – 2013-04-05 14:38:58

回答

2

您正在翻看望遠鏡的錯誤端。您不指定存儲變量的特定內存段(特別是因爲「內存段」的概念是高度依賴於平臺的)。

在C代碼,您決定變量的一生知名度可修改基於什麼有意義的代碼,並基於該編譯器將生成機器碼存儲的對象適當段(如適用)

例如,在文件範圍內聲明的變量(任何函數之外)或關鍵字static將有靜態存儲時間,這意味着他們在程序啓動時分配,並保持到程序終止;這些對象可以分配在數據段或bss段中。在沒有static關鍵字的函數或塊中聲明的變量具有自動存儲持續時間,並且(通常)在堆棧上進行分配。

字符串文字和其他編譯時常量對象通常(但並非總是)分配在只讀段中。像3.14159這樣的數字文字和'A'這樣的字符常量不是對象,並且通常沒有爲它們分配內存;相反,這些值直接嵌入機器代碼指令中。

堆被保留用於動態存儲,和變量因此不存儲在那裏;相反,您使用庫調用如malloc在運行時獲取堆的塊,並將結果指針值分配給如上所述分配的變量。 變量將存在於堆棧或數據段中,而其存儲器指向存在於堆上。

理想情況下,功能應完全通過參數,返回值和例外(如適用)進行通信;函數不應該通過外部變量(即全局)共享數據。函數參數通常分配在堆棧上,儘管有些平臺可能通過寄存器傳遞參數。

2

你應該更喜歡本地/堆棧變量時,這些變量是小全局或堆變量,經常使用,在相對小/有限的範圍內。這將使編譯器有更多機會使用它們來優化代碼,因爲它知道它們不會在函數調用之間進行更改,除非您傳遞指向它們的指針。

而且,堆通常是相對小的和大的分配結構或陣列上可能導致堆棧溢出,尤其如此遞歸代碼。

另一個要考慮的是使用在多線程程序的全局變量。要最大限度地減少競爭條件的機會,併爲一個戰略maiking功能線程安全的,並重新enterant通過不直接對他們使用任何全球資源(如果malloc()是線程安全的,如果errno是每個線程,等你能當然使用它們)。

順便說一句,使用局部變量而不是全局變量也提高了代碼的可讀性作爲變量靠近他們用在這個地方,你可以快速找出它們的類型和在何處以及如何他們使用。

除此之外,如果你的代碼是正確的,在變量本地或全局或堆中應該沒有太大的實際區別(當然,malloc()可能會失敗,你應該記住它:)。

0

僅C,可以指定其中數據經由可變的和/或分配的範圍存儲間接...。即一個函數的局部變量通常是一個棧變量,除非它被聲明爲靜態的,在這種情況下它可能是DATA/BSS。通過new/malloc動態創建的變量通常是堆。

但是,沒有任何保證......只有它的含義。

也就是說,保證是一個壞主意的一件事是在函數中聲明大的局部變量......奇怪的錯誤和堆棧溢出的常見來源。非常大的數組和結構最適合動態分配,並根據需要將指針保持在local/global中。