只为静态变量分配一次内存

allocate memory to static variable only once

本文关键字:一次 内存 静态 变量 分配      更新时间:2023-10-16

可能重复:
使用非常数初始值设定项定义全局变量

我有这个代码:

#include <stdio.h>
#include <stdlib.h>

int foo (int num, int i)
{
    static int* array = malloc(sizeof(int));  // ERROR HERE!!!
    printf("%d", array[i]);
    return 0;
}

int main(int argc, char *argv[])
{
    int i;
    for (i = 0; i < 2; i++) {
    foo(i, i);
    }
    return 0;
}

我把代码保存为c源文件,我不能工作?error prompt:

gcc -O2 -Wall test.c -lm -o test
test.c:4:1: error: initializer element is not constant
Compilation exited abnormally with code 1 at Sat Jan 05 21:33:56

然而,我把它保存为C++源文件,它工作正常。为什么?有人能向我解释吗?

您无法在C.中使用非常量初始化器初始化static对象

static int* array = malloc(sizeof(int));
                    ^ must be a constant

来自C标准:

(C99,6.7.8p4("具有静态存储持续时间的对象的初始化器中的所有表达式都应该是常量表达式或字符串文字。">

C和C++标准对具有static存储持续时间的对象的初始化处理不同。C++允许静态初始化(即用常量初始化(和动态初始化(即使用非常量表达式初始化(,而C只允许静态初始化,即使用常量表达式。

C++标准的相关部分是6.7.4:

具有静态存储持续时间(3.7.1(的所有本地对象的零初始化(8.5(在任何其他初始化发生之前执行。POD类型(3.9(的本地对象具有用常量表达式初始化的静态存储持续时间,在其块首次输入之前进行初始化。[…]否则,在控件第一次通过其声明时,会初始化此类对象;这样的对象在其初始化完成时被认为是初始化的(强调(

C++需要额外的"记账",以便只运行初始化器的动态部分(即malloc的调用(一次。在C标准中没有类似的"动态"条款:

所有具有静态存储持续时间的对象应在程序启动前进行初始化(设置为其初始值(。具有静态存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

在没有并发的情况下,您可以重写代码以便与C一起使用,如下所示:

int foo (int num, int i) {
    static int* array = NULL;
    if (!array) array = malloc(sizeof(int)); // No error
    printf("%d", array[i]);
    return 0;
}

现在您的代码负责"记账":它在执行分配之前检查arrayNULL

C(与C++不同(不允许初始化具有非常数值的静态持续时间变量。

static int* array = malloc(sizeof(int));  // ERROR HERE!!!

C99标准:第6.7.8节:

具有静态存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

这在C中是特权,但在C++中可以,它们是不同的

可以写如下:

static int* array = NULL;
if (array == NULL)
    array = malloc(sizeof(int));