存储与访问元素指针数组时是否符合C语言严格别名规则?
关于C语言严格别名规则与
some_array结构体的合规性疑问 结构体定义
struct some_array { void *elements; int nof_elements; bool has_pointers; };
其中elements成员既可以是my_type类型元素的数组,也可以是指向my_type类型元素的指针数组,具体类型由has_pointers的值决定。
内存分配示例
直接分配my_type数组
struct some_array arr = {.nof_elements = 10}; arr.has_pointers = false; arr.elements = malloc(arr.nof_elements * sizeof(my_type));
分配my_type*指针数组并初始化
struct some_array arr = {.nof_elements = 10}; arr.has_pointers = true; arr.elements = malloc(arr.nof_elements * sizeof(my_type *)); for (size_t i=0; i<arr.nof_elements; i++) { ((my_type**)arr.elements)[i] = malloc(sizeof(my_type)); }
元素访问逻辑
my_type *elmt; if (arr->has_pointers) { elmt = ((my_type **)arr->elements)[i]; } else { elmt = &((my_type *)arr->elements)[i]; }
核心疑问
假设has_pointers成员已根据elements的实际内容正确设置,代码能正常运行,但不确定这种结构是否符合严格别名规则?是否违反C语言规范中的如下规定?
对象的存储值只能通过具有以下类型之一的左值表达式访问:
—— 与对象的有效类型兼容的类型,
同时对该场景下“有效类型”的定义应用,以及语句中“兼容”的含义存在困惑。
解答
关键概念厘清
- 有效类型:通过
malloc等动态分配函数获得的内存,其有效类型是首次用于访问该内存的左值类型;后续若通过兼容类型修改内存,有效类型可能会同步调整,但本场景中我们始终按初始分配的类型访问,无需考虑后续修改的情况。 - 类型兼容:C标准中,兼容类型的核心判定逻辑是:
- 相同的算术、枚举、指针、结构体/联合体类型(结构体/联合体要求成员的名称、类型、顺序完全一致);
- 指向兼容类型的指针彼此兼容;
void*与任何对象指针类型兼容(用于类型转换场景)。
代码合规性分析
你的代码完全符合严格别名规则,理由如下:
- 当
has_pointers = false时,elements指向的是my_type数组,访问时将void*转换为my_type*,这个转换合法,且访问时使用的my_type*与内存的有效类型(my_type元素组成的数组)完全兼容,不存在类型不匹配的访问。 - 当
has_pointers = true时,elements指向的是my_type*数组,访问时将void*转换为my_type**,同样合法,访问类型与内存的有效类型(my_type*元素组成的数组)兼容。
严格别名规则禁止的是用不兼容的类型访问同一内存区域(例如用int*访问float类型的对象),而你的代码通过has_pointers确保了每次访问的类型都与内存实际的有效类型完全匹配,因此不会触发规则冲突。
另外需要说明:void*作为通用指针的设计初衷,就是用于在不同对象指针类型之间中转,只要转换回正确的原始类型(或兼容类型),就不会产生严格别名问题。
内容的提问来源于stack exchange,提问作者Reinier Torenbeek
相关产品推荐
相关产品推荐

