C语言中成员完全相同的匿名结构体是否属于兼容类型?
C语言匿名结构体指针转换合法性判定
问题相关代码
#include <threads.h> int thread_start(void *ptr) { struct { int a; int b; } *data = ptr; return 0; } int main(int argc, char *argv[]) { struct { int a; int b; } data; thrd_t thread; thrd_create(&thread, thread_start, &data); thrd_join(thread, NULL); return 0; }
问题
若两个匿名结构体的成员完全一致,请问上述代码中将void *转换为struct { int a; int b; } *的操作,是否属于C标准明确定义的合法行为?
回答
结论:该操作不属于C标准明确定义的合法行为,属于未定义行为。
原因如下:
- C标准对结构体类型兼容有明确约束,根据C11标准§6.2.7的规定,两个结构体要属于兼容类型,需要同时满足结构体标记(tag)相同、成员的数量、类型、声明顺序完全一致,位域宽度也完全匹配。
- 同一个翻译单元内的两个匿名结构体,哪怕成员的所有属性都完全一致,也会被C标准识别为两个完全独立的互不兼容的类型。上述代码中分别定义在
thread_start函数内部和main函数内部的两个匿名结构体,就属于这种不兼容的不同类型。 void *指针确实可以被转换为任意对象指针类型,但该转换的合法前提是转换后的指针类型和原指针指向的实际对象类型兼容,否则后续对转换后的指针解引用的行为属于未定义行为。
如果要让这段代码行为符合标准定义,可以给该结构体添加公共的结构体标记,或者通过typedef定义公共的结构体类型别名,保证两处使用的是同一个结构体类型即可。
内容的提问来源于stack exchange,提问作者Jim Morrison
相关产品推荐
相关产品推荐

