关于C语言复合字面量存储期及Clang与GCC编译差异的技术问询
关于C语言复合字面量存储期及Clang与GCC编译差异的技术问询
测试代码
先贴出我写的这段测试代码:
#include <stdio.h> struct s { int *i; }; void f(struct s *foo, const int a, const int b) { foo->i = (int []){a, b}; } int main(void) { struct s foo = {0}; f(&foo, 34, 35); printf("%d\n", foo.i[0]); return 0; }
编译运行差异
我分别用Clang和GCC编译运行了这段代码,结果出现了明显差异:
Clang 编译运行情况
版本信息和编译输出如下,全程没有任何警告或错误,运行结果正常:
% clang --version Apple clang version 17.0.0 (clang-1700.6.3.2) Target: arm64-apple-darwin24.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin % clang -Wall -Wextra -o main main.c && ./main 34
GCC 编译运行情况
GCC则直接抛出了悬垂指针的警告,但运行结果同样输出了34:
% gcc --version gcc (Homebrew GCC 15.2.0) 15.2.0 Copyright (C) 2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % gcc -Wall -Wextra -o main main.c && ./main main.c: In function 'f': main.c:9:12: warning: storing the address of local variable '({anonymous})' in '*foo.i' [-Wdangling-pointer=] 9 | foo->i = (int []){a, b}; | ~~~~~~~^~~~~~~~~~~~~~~~ main.c:9:22: note: '({anonymous})' declared here 9 | foo->i = (int []){a, b}; | ^ main.c:7:18: note: 'foo' declared here 7 | void f(struct s *foo, const int a, const int b) | ~~~~~~~~~~^~~ 34
我的个人理解
结合C语言的规则,我有这些初步想法:
- 按照标准,函数
f里的复合字面量(int []){a, b}属于自动存储期,它的生命周期只到f函数执行完毕就结束。理论上,main函数里通过foo.i访问这个数组属于访问已销毁对象,是未定义行为。 - 但实际运行时程序既没崩溃也输出了正确结果,我猜是编译器做了某种优化,自动规避了潜在的问题。
想请教的问题
- 既然代码运行没出问题,是不是编译器偷偷把这个复合字面量
(int []){34, 35}放到了全局作用域,让它变成了静态存储期? - 为什么Clang完全没检测出这个悬垂指针的风险,而GCC却给出了明确的警告?这俩编译器的检查逻辑或者优化策略有什么不同?
- (手动狗头)顺便吐槽一句,我要不要直接弃用Clang啊哈哈,当然是开玩笑的😅




