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

C语言是否允许NRVO形式复制消除?下述程序退出值是否有明确保证?

关于C语言NRVO复制消除及程序退出值的问题

问题内容

  • C语言是否允许以**named return value optimization(NRVO,具名返回值优化)**形式进行复制消除?
  • 下述C程序是否保证以0退出?还是编译器可以像C++中允许的那样,将对象s和t视为同一对象?

给出的代码如下:

typedef struct {
    int i, j;
    double a, b;
} S;

int result;

S test(S *q) {
    S s = {0, 0, 0, 0};
    result = &s == q;
    return s;
}

int main(void)
{
  S t = test(&t);
  return result;
}

注:Clang运行该程序退出值为1;在C++中因明确允许NRVO,0和1均为合法输出结果。

解答

1. C语言对NRVO形式复制消除的规定

C标准并未像C那样明确允许NRVO。不过C标准允许编译器进行**复制消除(copy elision)**优化,但适用场景与C存在差异:

  • C标准中的复制消除主要针对返回未命名临时对象的情况(类似C++的RVO),对于具名局部变量(如代码中的s)的返回优化,标准没有明确授权编译器将其与调用端对象(如t)合并。
  • 编译器可在不改变程序可观测行为的前提下优化,但C标准对变量的生存期和身份有严格要求:局部变量s是test函数内的独立对象,其地址必须与调用端的t不同,除非标准明确允许合并。

2. 程序的退出值分析

根据C标准规定,该程序必须保证以0退出:

  • test函数中的局部变量s是独立的自动存储期对象,它的地址&s和传入的&t(main中t的地址)是两个不同指针,因此&s == q的结果必为假,result会被赋值为0,程序最终返回0。
  • Clang返回1的行为违反了C标准,它错误套用了类似C++的NRVO优化,将s和t的存储合并,但C语言不允许编译器通过优化抹除两个不同对象的身份差异,指针比较结果必须符合对象实际存储位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:27:15