有些人不知道这是possible to pass and return structs by value in C.我的问题是关于编译器在C.中做 struct 时,不做拷贝,例如GCC使用Return value optimization(RVO)优化,或者这是C++的概念吗?我所读到的关于RVO和复制删除的内容都是关于C++的.

让我们考虑一个例子. 我目前正在C中实现double-double data type(或者更确切地说,从浮点-浮点开始,因为我发现它很容易进行单元测试).请考虑以下代码.

typedef struct {
    float hi;
    float lo;
} doublefloat;

doublefloat quick_two_sum(float a, float b) {
    float s = a + b;
    float e = b - (s - a);
    return (doublefloat){s, e};
}

编译器会对我返回的doublefloat个值进行临时复制,还是可以省略临时复制?

那么C语言中的命名返回值优化(NRVO)呢?我还有一个功能

doublefloat df64_add(doublefloat a, doublefloat b) {
    doublefloat s, t;
    s = two_sum(a.hi, b.hi);
    t = two_sum(a.lo, b.lo);
    s.lo += t.hi;
    s = quick_two_sum(s.hi, s.lo);
    s.lo += t.lo;
    s = quick_two_sum(s.hi, s.lo);
    return s;
}

在本例中,我将返回一个命名 struct .在这种情况下,临时副本可以省略吗?

应该指出的是,这是C语言的一个一般性问题,我在这里使用的代码示例只是示例(当我优化它时,我将使用SIMD和intrinsic).我知道我可以通过查看汇编输出来了解编译器的功能,但我认为这是一个有趣的问题.

推荐答案

根据C中的"仿佛"规则,RVO/NRVO是明确允许的.

用C++,你可以得到明显的副作用,因为你已经超载了构造函数、析构函数和/或赋值操作符来提供这些副作用(例如,当这些操作发生时打印出一些东西),但是在C中你没有能力过载那些运算符,而内置的没有任何明显的副作用.

在不重载它们的情况下,复制省略不会产生明显的副作用,因此没有什么可以阻止编译器这样做.

C++相关问答推荐

C中的整字母后缀i是什么

如何将字符串argv[]赋给C中的整型数组?

将fget()与strcMP()一起使用不是正确的比较

C中函数类型的前向声明

整型文字后缀在左移中的用途

Sizeof(&Q;字符串&Q;)的正确输出是什么?

为什么中断函数会以这种方式影响数组?

为什么我的Hello World EFI程序构建不正确?

如何读取文件并将内容保存在字符串中?(在C语言中,没有崩溃或核心转储错误)

如何在VS 2022中正确安装额外的C头文件

pthread_create的用法

Go和C中的数据 struct 对齐差异

错误:字符串在C中获得意外输出

为什么我的半数组测试和奇数组测试不起作用?(我使用Assert进行调试)

C23标准是否向后兼容?

在下面的C程序中,.Ap0是如何解释的?

C中的char**v*char[]

如何正确探测平台设备?

为什么需要struct in_addr

仅使用其内存地址取消引用 C 中的 struct