簡體   English   中英

為什么C和C ++編譯器將顯式初始化和默認初始化全局變量放在不同的段中?

[英]Why do C and C++ compilers place explicitly initialized and default initialized global variables in different segments?

我正在讀這篇關於C程序內存布局的精彩帖子 它表示默認初始化全局變量駐留在BSS段中 ,如果您明確地為全局變量提供值,那么它將駐留在數據段中

我已經在C和C ++中測試了以下程序來檢查這種行為。

#include <iostream>
// Both i and s are having static storage duration
int i;     // i will be kept in the BSS segment, default initialized variable, default value=0
int s(5);  // s will be kept in the data segment, explicitly initialized variable,
int main()
{
    std::cout<<&i<<' '<<&s;
}

輸出:

0x488020 0x478004

因此,從輸出中可以看出,變量i和s都存在於完全不同的段中。 但是如果我從變量S中刪除初始化程序(此程序中的初始值為5)然后運行程序,它會給我以下輸出。

輸出:

0x488020 0x488024

因此,從輸出中可以清楚地看出變量i和s都位於相同的(在這種情況下為BSS)段中。

這種行為在C中也是一樣的。

#include <stdio.h>
int i;      // i will be kept in the BSS segment, default initialized variable, default value=0
int s=5;    // s will be kept in the data segment, explicitly initialized variable,
int main(void)
{
    printf("%p %p\n",(void*)&i,(void*)&s);
}

輸出:

004053D0 00403004

因此,我們可以再次通過查看輸出(意味着檢查變量的地址)來說,變量i和s都位於完全不同的段中。 但是,如果我從變量S中刪除初始化程序(此程序中的初始值5)然后運行程序,它會給我以下輸出。

輸出:

004053D0 004053D4

因此,從輸出中可以清楚地看出變量i和s都位於相同的(在這種情況下為BSS)段中。

為什么C和C ++編譯器將顯式初始化和默認初始化全局變量放在不同的段中? 為什么全局變量在默認初始化變量和顯式初始化變量之間存在區別? 如果我沒有錯,那么C和C ++標准從不談論堆棧,堆,數據段,代碼段,BSS段以及所有特定於實現的事情。 那么,C ++實現是否有可能將顯式初始化和默認初始化變量存儲在相同的段中,而不是將它保存在不同的段中?

語言C或C ++都沒有“段”的概念,也不是所有操作系統都這樣做,所以你的問題不可避免地依賴於平台和編譯器。

也就是說,常見的實現方式將以不同方式處理初始化變量與未初始化變量。 主要的區別是,未初始化(或默認為0初始化)數據沒有實際被保存在編譯的模塊,但只申報/在運行時留作后用。 在實際的“段”條款,初始化的數據保存到磁盤作為二進制文件的一部分,同時未初始化的數據是不是 ,而是它在啟動時分配給滿足宣布“保留”。

真正簡短的回答是“因為它占用的空間更少”。 (正如其他人所說,編譯器不必這樣做!)

在可執行文件中, data部分將包含其值存儲在相對位置的數據。 這意味着對於初始化數據的每個字節,該數據部分包含一個字節。

對於零初始化的全局變量,沒有理由存儲大量的零。 相反,只需將整個數據集的大小存儲在一個單一的大小值中。 因此,不是在data分區中存儲4132個字節的零,而是只有“BSS長4132個字節” - 並且由OS /運行時設置為零。 - 在某些情況下,編譯器的運行時將是memset(BSSStart, 0, BSSSize)或類似的。 在例如Linux中,無論如何在創建進程時所有“未使用”的存儲器都填充為零,因此將BSS設置為零只是首先分配存儲器的問題。

當然,較短的可執行文件有幾個好處:硬盤上占用的空間更少,加載時間更短[如果操作系統預先填充分配的內存為零,則額外獎勵],編譯器/鏈接器不會更快編譯時間必須將數據寫入磁盤。

所以這有一個完全實際的原因。

根據定義,BSS不是一個不同的部分,它是數據部分的一部分。

在C和C ++中,沒有顯式初始化器的靜態分配對象被初始化為零,實現還可以為BSS部分分配靜態分配的變量和用僅由零值位組成的值初始化的常量。

將它們存儲在BSS中的原因是,可以在運行時獲得具有未初始化或默認值的那些類型的變量而不浪費二進制文件中的空間而不是放置在數據段中的變量。

暫無
暫無

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

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