函数作用域中const静态变量的内存分配

3
在C语言中,static const intconst int在内存分配方面有什么区别?
void f(int *a)
{
    static const int b = 10;
    const int c = 20;

    *a = b + c;
}

b只会消耗sizeof(int)吗?而c,对于值20,它会消耗sizeof(int),并在f执行期间产生一条复制指令,还是只会消耗sizeof(int)

4个回答

5
语言标准对此没有任何规定。
但是,编译器很可能会将您的代码转换为以下内容:
void f(int *a) {
    *a = 30;
}

因此,它根本不分配任何内存(除了指令空间,显然)。


1

考虑到函数内部两个常量都是已知的,编译器有什么阻止它将其变为*a = 30;的理由吗?在这个例子中,bc都不一定需要存储空间。

如果需要存储空间:

 static const int b = 10;

将占用一个sizeof(int)的空间[可能由于填充而使用更多空间,这取决于数据部分中a之前和之后出现了什么,并且没有说明编译器将为任何给定情况提供多少填充-无论是必要的还是不必要的,以使事情在编译器针对的系统上“正常工作”]。根据系统的架构,可能需要代码来设置b = 10 [有关其大小的信息请参见下文]。

 const int c = 20; 

在堆栈上可能会占用sizeof(int)字节,但也会有代码来初始化b为20 - 这可以是任何小数字 - 2、3、5、6、7、8、16或类似的数字,这取决于处理器架构和所需的指令类型。当然,编译器可以直接在需要的地方使用20。

但编译器要求的只是将*a设置为30,其他所有内容都是“由编译器决定”的。


1

静态常量将在程序执行期间分配一次。

函数内的常量将在每次进入函数时分配到堆栈上,并在退出时从堆栈中释放。

我可能需要指出上面的“然而,编译器很可能会将您的代码转换为这样:”是不正确的。如果您请求“static”存储类,则没有编译器会忽略它,静态变量可以用于传递指针等其他原因。


如果OP的代码确实就是按照所写的那样,那么它可以像我的答案一样被“转换”。 - Oliver Charlesworth
我的gcc(4.6.2)和clang(3.0)从“-O”开始消除它。 - Daniel Fischer
没错。我想我更多地是在回答关于存储类问题的角度,而不是提供的代码。 - B. Nadolson

0
在您的示例中,它们的含义相同,并且正如@Oli所提到的,编译器将优化它,以使实际代码甚至可能不在最终代码中。
但是这里有一个不同的用例:
int func1(int v) {
 const int c_i = compute_some_things(v);/* calculate the c_i everytime we enter this function */
 return c_i = v + c_i;
}


int func2(int e) {
 static const int c_i = compute_some_things_one_time();/* c_i is calculated ONCE, the next time, the value of c_i is retained every time the function is entered */
 return c_i = e + c_i;
}

我已经知道这个用例,我想知道在定义“真正”的常量时内存消耗情况。 - Spidey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接