C:通过堆栈/寄存器问题返回值

Ily*_*lya 15 c function return-value calling-convention

我是C的新手,有一件事我无法理解.当函数返回不大于寄存器的东西时 - 我的编译器把它放在EAX中.当我返回大结构(不是指针而是结构本身)时 - 它通过堆栈返回.

我的问题是:编译器如何知道如何调用另一个对象导出的函数?有一个调用约定(比如stdcall)但它是关于传递参数,而不是读取返回的值,对吧?

应该有一些规则,如"如果声明的返回值大于EAX,则从[bp -...]"获取.

还有一个:是否正确地说我想要返回的对象,比寄存器大,应该存储在堆中并由指针返回以防止所有堆栈操作?

谢谢.

Jon*_*Jon 18

返回值传递给调用者的方式也是函数调用约定的一部分.看到这里.

例如,关于cdecl:

cdecl调用约定是由许多C系统的x86架构使用.在中cdecl,函数参数以从右到左的顺序被压入堆栈.函数返回值在EAX寄存器中返回(浮点值除外,它们在x87寄存器ST0中返回).

[...]
Run Code Online (Sandbox Code Playgroud)

解释有一些变化cdecl,特别是如何返回值.因此,为不同的操作系统平台和/或不同的编译器编译的x86程序可能是不兼容的,即使它们都使用cdecl约定而不调用底层环境.一些编译器在EAX:EDX中返回长度为2个寄存器或更少的简单数据结构,并且需要异常处理程序(例如,定义的构造函数,析构函数或赋值)进行特殊处理的较大结构和类对象在内存中返回.为了传递"in memory",调用者分配内存并将指针作为隐藏的第一个参数传递给它; callee填充内存并返回指针,返回时弹出隐藏的指针.

如果在堆上分配内存,堆栈操作将比必要的堆操作快得多,因此堆栈总是更快.唯一的原因(在C中)你可能想要返回指向堆上的东西的指针是因为它不适合堆栈.

澄清:

在上面的最后一句中,"你可能想要的唯一理由......"不应被解释为"通常没有理由返回指针".相反,我的意思是" 如果你能在不返回指针的情况下做你需要的东西,那么决定使用指针的唯一理由就是......".

当然,有很多正当理由可以回答Chris的功能,因为Chris在他自己的回答中说,但我只是在讨论你不需要这样做的情况.

换句话说,尽可能按价值返回; 必要时使用指针.

  • @flow2k 非常粗略:堆栈的组织方式使其可以非常快速地操作;您通过接受对其分配的内存的相对生命周期的限制来为此付出代价。堆不存在任何此类限制,但您通过接受更多簿记成本来为此付出代价。 (2认同)