如何C编译器实现返回大的结构功能呢? [英] How do C compilers implement functions that return large structures?

查看:147
本文介绍了如何C编译器实现返回大的结构功能呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

函数的返回值通常被存储在堆栈或寄存器。但对于一个大的结构,它必须是在堆栈中。多少复制在此code真正的编译器发生呢?抑或是优化掉?

The return value of a function is usually stored on the stack or in a register. But for a large structure, it has to be on the stack. How much copying has to happen in a real compiler for this code? Or is it optimized away?

例如:

struct Data {
    unsigned values[256];
};

Data createData() 
{
    Data data;
    // initialize data values...
    return data;
}

(假设不能被内联函数..)

(Assuming the function cannot be inlined..)

推荐答案

无;不需要拷贝。

呼叫者的数据返回值的地址实际上是作为隐藏参数传递给函数,而createData函数只是写入到调用者的堆栈帧。

The address of the caller's Data return value is actually passed as a hidden argument to the function, and the createData function simply writes into the caller's stack frame.

这就是所谓的命名返回值优化。另见本专题中的 C ++ FAQ。

This is known as the named return value optimisation. Also see the c++ faq on this topic.

商业级的C ++编译器实现的方式,让他们消除了开销,收益按值至少在简单的情况下

commercial-grade C++ compilers implement return-by-value in a way that lets them eliminate the overhead, at least in simple cases

...

当您的code()调用RBV(),编译器偷偷将指针传递到RBV()假设来构造的位置返回对象。

When yourCode() calls rbv(), the compiler secretly passes a pointer to the location where rbv() is supposed to construct the "returned" object.

您可以证明,这是通过添加一个析构函数与一个printf你做的结构。如果该返回按值的优化是在操作中,否则两次析构应该只被调用一次。

You can demonstrate that this has been done by adding a destructor with a printf to your struct. The destructor should only be called once if this return-by-value optimisation is in operation, otherwise twice.

你也可以检查装配一看就知道发生什么:

Also you can check the assembly to see that this happens:

Data createData() 
{
    Data data;
    // initialize data values...
    data.values[5] = 6;
    return data;
}

这里的集会:

__Z10createDatav:
LFB2:
        pushl   %ebp
LCFI0:
        movl    %esp, %ebp
LCFI1:
        subl    $1032, %esp
LCFI2:
        movl    8(%ebp), %eax
        movl    $6, 20(%eax)
        leave
        ret     $4
LFE2:

奇怪的是,它在栈中的数据项 subl $ 1032%ESP ,但要注意,它需要在堆栈上的第一个参数<$ C $在分配足够的空间C> 8(%EBP)作为对象的基地址,然后初始化该项目的元件6。由于我们没有指定任何参数createData,直到你意识到这是秘密藏指针数据的父母的版本,这是奇怪的。

Curiously, it allocated enough space on the stack for the data item subl $1032, %esp, but note that it takes the first argument on the stack 8(%ebp) as the base address of the object, and then initialises element 6 of that item. Since we didn't specify any arguments to createData, this is curious until you realise this is the secret hidden pointer to the parent's version of Data.

这篇关于如何C编译器实现返回大的结构功能呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆