You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何返回C99复合字面量会生成更多汇编代码?

问题:为何复合字面量返回结构体比变量初始化返回生成更多汇编代码?

给出的两个C函数,一个通过复合字面量返回结构体,另一个先初始化变量再返回:

typedef struct {
    int storage[256];
} data_t;

data_t data_init_compound_literal() {
    return (data_t){
        .storage = {1}
    };
}
data_t data_init_var() {
    data_t self;
    self.storage[0] = 1;
    return self;
}

int main(void) {
    data_t em = data_init_compound_literal();

    return em.storage[0];
}

使用-O2优化选项生成汇编后,复合字面量方式的函数生成的代码行数明显更多:

data_init_compound_literal:
  movq $0, (%rdi)
  movq %rdi, %rdx
  leaq 8(%rdi), %rdi
  xorl %eax, %eax
  movq $0, 1008(%rdi)
  movq %rdx, %rcx
  andq $-8, %rdi
  subq %rdi, %rcx
  addl $1024, %ecx
  shrl $3, %ecx
  rep stosq
  movl $1, (%rdx)
  movq %rdx, %rax
  ret
data_init_var:
  movl $1, (%rdi)
  movq %rdi, %rax
  ret
main:
  movl $1, %eax
  ret
原因解析

两者的核心差异源于C语言标准对初始化行为的不同要求:

  • 复合字面量的(data_t){.storage = {1}}属于聚合初始化,根据C标准,聚合类型中未显式指定的元素必须被初始化为对应类型的零值(这里就是int的0)。因此编译器必须生成代码,将整个storage数组的256个元素全部清0,再把第一个元素设为1。
  • 而data_init_var函数中,局部结构体变量self默认是未初始化状态(栈上的原始垃圾值),标准没有要求未赋值的元素必须为0,编译器只需要保证storage[0]被设为1即可,其他元素无需处理。

在-O2优化下,编译器严格遵循标准规则:

  • 复合字面量版本需要完成全数组的清0操作,汇编中出现的rep stosq就是批量写0的高效指令,用来初始化整个数组,这也是代码行数更多的原因。
  • 变量初始化版本仅需设置第一个元素的值,因此汇编代码极为简洁。

注:main函数的汇编被优化为直接返回1,是因为编译器能直接推导函数调用的最终结果,属于独立的优化,和两个初始化函数的差异无关。

内容的提问来源于stack exchange,提问作者edugomez102

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:28:13