g++编译C代码:灵活数组成员两种初始化方式的差异解析
问题解析:柔性数组成员结构体指针数组的两种初始化差异
两种初始化方式的核心区别
1. 全局/静态变量初始化(可正常编译)
你定义的x和y是全局变量,属于静态存储期对象。对于带柔性数组成员的结构体,C标准允许用初始化列表为全局/静态变量的柔性数组赋值——编译器在编译时就能根据初始化列表里的元素数量,计算出整个结构体的实际大小(sizeof(HasArray) + 元素字节数),并分配足够的内存空间。g++兼容C的这一规则,因此可以正常编译。
2. 复合字面量取地址(编译报错)
你用&(HasArray){...}的方式是C的复合字面量语法,但g在处理时,会把未加static修饰的复合字面量视为临时对象(类似C中的临时值)。而C标准本身对柔性数组成员的支持有限,且g禁止对临时对象进行柔性数组成员的非静态初始化——编译器认为临时对象的生命周期和内存分配规则无法适配柔性数组的动态大小需求,因此抛出"non-static initialization of a flexible array member"错误。
不创建单独变量的解决方案
给复合字面量加上static修饰,将其转为静态存储期对象,让编译器在编译时确定内存大小并分配空间,写法如下:
#include <stdint.h> typedef struct { uint16_t num_elements; uint8_t elements[]; } HasArray; const HasArray* collection[] = { &((static HasArray){.num_elements = 2, .elements = {51, 17}}), &((static HasArray){.num_elements = 4, .elements = {1, 42, 88, 73}}) };
这样处理后,复合字面量的存储方式和全局变量x、y完全一致,g++就能正常识别并分配正确的内存空间。
补充说明
由于你是用g编译C代码,g会同时兼顾C和C的规则,这和纯gcc编译C代码的行为有差异:纯gcc编译第二种未加static的复合字面量代码通常可以通过,但g因为要符合C++对临时对象的限制,所以会报错。
内容的提问来源于stack exchange,提问作者Quantasm
相关产品推荐
相关产品推荐

