C语言不同翻译单元同名struct不同定义是否属于未定义行为
现有代码示例
0.c
#include <stdio.h> struct test{ int a; }; struct test get(int in); int main(){ struct test t = get(1234); printf("%d\n",t.a); return 0; }
1.c
struct test{ char a; // 此处成员为char而非int }; struct test get(int in){ struct test t = {in}; return t; }
问题解答
这段代码属于明确的未定义行为。
很多人对C语言的规则存在片面误解:C语言确实没有C++那样成文的单一定义规则(ODR),也允许不同翻译单元定义同名结构体,但前提是这些同名结构体没有和跨单元调用的外部资源绑定:
- 如果两个翻译单元的同名
struct test仅在各自单元内部使用,没有关联任何跨单元调用的外部函数、外部变量,那这种用法完全合法:两个结构体只是名字碰巧相同,本质是完全独立的两个类型,互不干扰。 - 但本示例的核心问题在于,跨翻译单元的外部函数
get的声明和实现类型不兼容:- 0.c中声明的
get函数返回值是包含int成员的struct test,常规大小为4字节 - 1.c中实现的
get函数返回值是包含char成员的struct test,常规大小为1字节
C标准明确要求,所有对具有外部链接的同一个函数的声明,必须指向兼容类型,否则就属于未定义行为。这里两个get函数的返回类型是完全不兼容的结构体,完全符合未定义行为的判定条件。
- 0.c中声明的
实际运行时可能出现多种不可预期的结果:比如打印1234的低8位数值、打印随机乱数、程序直接崩溃等,都是未定义行为的典型表现。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

