簡體   English   中英

在if塊中聲明一個從未命中的函數級靜態變量

[英]Declaring a function level static variable inside an if block that is never hit

我對函數內部聲明的靜態變量的理解是:

  1. 如果未指定初始值,則靜態變量將駐留在.bss ,否則將駐留在.data
  2. 靜態的內存與全局變量一起分配 - 即,在執行進入main之前
    • 這兩個假設是否正確
  3. 當執行第一次執行該函數時,靜態將初始化為用戶指定的值(如果未指定初始值,則為零)。
  4. ......並且它們在函數的后續調用中保留其值

但是,如果我在if塊中聲明我的靜態變量怎么辦? 我假設我的第三點應該更新為“當執行到達聲明靜態變量的行時,它們被初始化為......” - 我是對的嗎?

現在,如果它們被聲明的if塊永遠不會被命中(並且編譯器能夠解決這個問題) - 我知道該變量永遠不會被初始化; 但是為該變量分配了任何內存嗎?

我寫了兩個函數來試圖弄清楚發生了什么:

#include <stdio.h>

void foo()
{
    static foo_var_out;
    if(0){
        static foo_var_in_0;
        printf("%d %d\n", foo_var_in_0);
    } else {
        static foo_var_in_1;
        printf("%d %d\n", foo_var_in_1);
    }   
}

static void bar(int flag)
{
    static bar_var_out;
    if(flag){
        static bar_var_in_0;
        printf("%d %d\n", bar_var_in_0);
    } else {
        static bar_var_in_1;
        printf("%d %d\n", bar_var_in_1);
    }   
}

int main()
{
    foo();
    bar(0);
}

我拿了對象轉儲:

$ gcc -o main main.c
$ objdump -t main | grep var
45:080495c0 l     O .bss    00000004              foo_var_in_1.1779
46:080495c4 l     O .bss    00000004              foo_var_out.1777
47:080495c8 l     O .bss    00000004              bar_var_in_1.1787
48:080495cc l     O .bss    00000004              bar_var_in_0.1786
49:080495d0 l     O .bss    00000004              bar_var_out.1785

從輸出看起來好像foo_var_in_0沒有創建foo_var_in_0 (可能是因為它在顯式if(0) ),而bar_var_in_0被創建(因為調用者可以傳遞非零值 - 盡管唯一的調用者顯式傳遞零)。

我想我的問題是:假設根本沒有為變量foo_var_in_0分配內存是否正確? 我在問這個具體案例; 我是否正確地閱讀了objdump - 或者我應該做更多的事情來驗證變量是否會在程序運行時占用一些內存?

換句話說,如果從未命中聲明函數級靜態變量的行,那么變量實際上是否已聲明?

如果它根本不會被創建,那么這是根據C標准(不太可能),還是編譯時優化以及在什么級別 - 如何將其打開/關閉(在gcc 4.1.1中)?

我知道一個int並不是一個值得關注的大問題,但我對它的工作原理更感興趣; 如果變量是一個大的數組,比如一個10字節結構的5000個元素,該怎么辦?

假設根本沒有為變量foo_var_in_0分配內存是否正確?

不,我不認為這是正確的。 據我所知,這樣的優化不是標准的一部分。

如果您知道編譯器執行此操作並且您想要假設它,請繼續。 如果您編寫需要這樣的任何內容,您可能需要編寫一個構建后測試以確保它發生。

也許,你所看到的是編譯器的副作用,只是修剪了一些它知道永遠不會運行的代碼。 意思是,它不是專門想要刪除靜態,但它確實刪除了整個分支,因此其中的任何代碼也被刪除了。

C標准沒有規定放置變量和內容的位置。 它只是規定符合要求的實現應具有等效行為(對於標准規定的參考行為),其中“等效”也由標准定義。

所以簡單的答案是它是一個優化,如何打開/關閉它取決於特定的編譯器。

進行過程間分析的實現可能也可以擺脫bar_var_in_0

只是為了增加其他人的正確答案。 關於static變量初始化的假設是不正確的。

  • 始終初始化具有靜態存儲的變量。 如果您提供初始化程序或從0隱式提供,則顯式。
  • 這種變量的初始化程序必須始終是編譯時常量表達式。 因此,該值在編譯時計算並直接寫入對象。 (如果全部為零,則某些系統會有一些技巧/特殊部分,以避免在目標文件中顯式存儲變量。)
  • 所以,不,當第一次訪問變量時,將不會運行初始化語句(系統將如何通過另一個靜態變量的值知道?)但是無論何時啟動程序,變量都已初始化。

暫無
暫無

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

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