2016-10-04 207 views
1

正如標題所說,在FLASH中佔用更多空間(例如,在STM32μC中)?聲明一個全局變量或聲明一個函數內的靜態變量?還是他們採取平等的空間?根據我的理解,這兩個變量在整個程序運行時都可用。他們的範圍是不同的。什麼在FLASH中佔用更多空間?靜態變量或全局變量

+2

這些變量的行爲方式相同。 Flash佔用的區別在於未初始化(自動初始化爲「0」)和初始化變量。在第二種情況下,值通常存儲在閃存的'data section'中。 – LPs

回答

4

您可以使用0初始化的全局變量和靜態變量。那些通常不會閃光,因爲它們被放置在存儲位置,當程序啓動時它們被分配並歸零,並且不是來自閃光。

您也可以使用值初始化變量。在這種情況下,它們被放置在初始化的數據段中,因此根據數據類型的大小佔用閃存的空間。

函數內部的靜態變量也可以用代碼初始化。初始化必須在運行時發生,但只能發生一次,所以它實際上會生成更多的代碼,幾乎在任何情況下都會佔用比數據大小更多的空間(不一定,至少如果您使用函數返回值)。對於非常量全局變量,您也可以做同樣的事情,您只需要將它們初始化爲0,然後將賦值(例如)放在main()的開始位置,其中它的作用與初始化函數作用域靜態變量的位置相同代碼需要在別處。

結論:全局和功能範圍的靜態變量佔用相同的空間量。


上面假定嵌入式上下文中的「全局變量」或文件範圍靜態變量。如果它是在可動態鏈接的可執行文件中導出全局符號,那麼該符號的重定位信息將在可執行二進制文件中佔用一些空間。但是,我不認爲給出的示例系統支持或使用可重定位的可執行文件。

1

「整個運行期間可用」的正式術語是靜態存儲期限。在文件範圍(「全局」)聲明的變量以及用static聲明的所有變量均具有靜態存儲持續時間。

因此,範圍和存儲時間之間有一個關係:範圍可以決定變量獲得的存儲持續時間。但範圍和內存使用量之間沒有關係。

變量佔用多少空間取決於變量類型的大小。範圍和存儲時間與它無關。

在大多數編譯器/鏈接,通常有兩種閃光燈落得一個變量所需的東西:

  • 必須聲明爲const
  • 它必須具有靜態存儲時間

如果這些條件不滿足,則變量將不會在閃蒸/ NVM結束,無論哪個範圍則在聲明的。

+0

如果它不是'const',那麼「變量不會以flash/nvm結尾」是什麼意思?我的意思是,初始值來自某個地方,所以如果它不是直接作爲數據(加載到RAM)閃存,那麼它必須作爲代碼存儲在閃存中。但是,爲什麼如果在編譯時知道值,因爲代碼將佔用更多空間並增加啓動時間? (注意,我不是嵌入式內容的專家,這是一個嚴重的問題。) – hyde

+0

@hyde如果它不是const,那麼它是一個讀/寫變量。讀/寫變量顯然不能在閃存中分配。如果這樣的變量具有初始化器,那麼初始化器確實存儲在閃存中,並在初始化期間寫入變量。 – Lundin

+0

因此,你所說的是,當閃存映射到CPU地址空間並直接訪問時,const變量可能不會佔用任何「正常」/易失性RAM。但是我會將問題的「佔用更多空間」解釋爲包括通過在源代碼中定義變量而添加的任何初始化數據或代碼。 – hyde

0

正如標題所說,什麼在FLASH中佔用更多空間(例如在STM32μC中)?聲明一個全局變量或聲明一個函數內的靜態變量?還是他們採取平等的空間?

使用arm-none-eabi-gcc作爲STM32構建的參考,根本不佔用任何閃存空間。

未申報const去任何進入.data部分,如果他們需要啓動初始化或進入.bss如果他們不這樣做全局和靜態變量。這兩個段都通過鏈接器腳本放入SRAM中。如果你正在執行C++,那麼靜態C++類將以.bss結尾。

如果您確實聲明瞭const,那麼它們將被放入.rodata部分,如果您諮詢鏈接描述文件,您應該發現它位於.text的閃存分段中。 Flash通常比SRAM更豐富,所以請儘可能使用const

最後,優化器可以出現並完全重新排列它認爲合適的任何東西,包括取消存儲以支持內聯。