You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于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访问这个数组属于访问已销毁对象,是未定义行为。
  • 但实际运行时程序既没崩溃也输出了正确结果,我猜是编译器做了某种优化,自动规避了潜在的问题。

想请教的问题

  1. 既然代码运行没出问题,是不是编译器偷偷把这个复合字面量(int []){34, 35}放到了全局作用域,让它变成了静态存储期?
  2. 为什么Clang完全没检测出这个悬垂指针的风险,而GCC却给出了明确的警告?这俩编译器的检查逻辑或者优化策略有什么不同?
  3. (手动狗头)顺便吐槽一句,我要不要直接弃用Clang啊哈哈,当然是开玩笑的😅

火山引擎 最新活动