在if块中声明一个从未命中的函数级静态变量

Ama*_*osh 6 c

我对函数内部声明的静态变量的理解是:

  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);
}
Run Code Online (Sandbox Code Playgroud)

我拿了对象转储:

$ 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
Run Code Online (Sandbox Code Playgroud)

从输出看起来foo_var_in_0根本就没有创建(大概是因为它在显式内部if(0)),而是bar_var_in_0被创建(因为调用者可以传递非零值 - 尽管唯一的调用者显式传递零).

我想我的问题是:假设根本没有为变量分配内存是否正确foo_var_in_0?我在问这个具体案例; 我是否正确地阅读了objdump - 或者我应该做更多的事情来验证变量是否会在程序运行时占用一些内存?

换句话说,如果从未命中声明函数级静态变量的行,那么实际上是否声明了变量?

如果它根本不会被创建,那么这是根据C标准(不太可能),还是编译时优化以及在什么级别 - 如何将其打开/关闭(在gcc 4.1.1中)?

我知道一个int并不是一个值得关注的大问题,但我对它的工作原理更感兴趣; 如果变量是一个大的数组,比如一个10字节结构的5000个元素,该怎么办?

Lou*_*nco 4

假设根本没有为变量 foo_var_in_0 分配内存是否正确?

不,我认为这样的假设是不正确的。据我所知,像这样的优化不属于标准的一部分。

如果您知道编译器会执行此操作并且您想假设它,请继续。如果您编写任何需要这种情况的内容,您可能需要编写构建后测试以确保它发生。

也许,您所看到的是编译器的副作用,只是删除了一些它知道永远不会运行的代码。这意味着,它并不是专门希望删除静态数据,但它确实删除了整个分支,因此其中的任何代码也被删除了。