使用复合字面量时的C语言错误:数组初始化自非常量数组表达式
为什么用复合字面量初始化普通数组会报错?
原代码的问题
你写的代码:
int a[2] = (int[2]){1,2};
之所以报错,核心是C语言(包括GNU扩展)不允许用复合字面量作为普通自动存储期数组的初始化器。
C标准中,自动数组(函数内不带static的局部数组)的初始化规则很明确:初始化器必须是用{}包裹的初始化列表,而不能是一个数组类型的表达式(复合字面量本质是一个临时数组对象,属于表达式范畴)。哪怕这个表达式的元素都是常量,也不符合自动数组的初始化语法要求。
编译器报错的解释
你疑惑“1和2都是常量,为什么说非常量数组表达式”——这里的关键点是:编译器报错指的是复合字面量这个整体不是合格的常量初始化器,而非元素不是常量。
复合字面量(int[2]){1,2}本身是一个运行时创建的临时数组表达式(哪怕元素是编译期常量),它不属于C标准规定的“适用于自动数组初始化的常量表达式”范畴。只有直接的{1,2}这种初始化列表,才是自动数组允许的初始化形式。
两种修改方案的合法性
- 改成指针赋值:
int* a = (int[2]){1,2};
这里复合字面量会被隐式转换为指向其首元素的指针,把这个指针赋值给指针变量a是完全合法的。需要注意:如果这段代码在函数内部,这个复合字面量的生命周期和局部变量一致,退出当前作用域后就会被销毁,后续再通过a访问会导致未定义行为。
- 改成静态数组初始化:
static int a[] = (int [2]) {1, 2};
这符合GNU扩展的规则:当复合字面量的所有元素都是适用于静态存储期对象初始化的常量表达式时,它可以被用来初始化静态数组。此时复合字面量会被处理为静态存储的数组,和目标静态数组的生命周期一致,初始化是合法的。
内容的提问来源于stack exchange,提问作者fdc
相关产品推荐
相关产品推荐

