函数的返回值通常存储在堆栈或寄存器中.但对于大型结构,它必须在堆栈上.在这个代码的真实编译器中必须进行多少复制?还是优化了?
例如:
struct Data {
unsigned values[256];
};
Data createData()
{
Data data;
// initialize data values...
return data;
}
Run Code Online (Sandbox Code Playgroud)
(假设函数无法内联..)
c compiler-theory abi calling-convention compiler-optimization
结构是值类型,因此每次对结构进行操作时都会完全复制。由于它们是值类型,因此结构在堆栈中分配,而不是在堆中分配。
我可以看到当结构作为参数传递时,结构如何降低方法的性能,因为它们总是在堆栈中复制,特别是如果它们很大并且有很多内部字段。
但我很好奇 C# 如何处理结构的返回。
在 C 中,返回是通过寄存器进行的,或者如果要返回的值对于寄存器而言太大,则通过使用堆的引用进行返回。几乎所有 C# 结构教程都说结构存在于堆栈中,而不是存在于堆中。
所以在下面的代码中:
MyStruct ms = GetMyValue();
Run Code Online (Sandbox Code Playgroud)
哪里GetMyValue()
MyStruct GetMyValue();
Run Code Online (Sandbox Code Playgroud)
C# 将如何处理 ms 变量的结构返回?特别是如果它对于寄存器来说太大了?它实际上会将其复制到堆中,然后再次将其复制回方法的调用者并将其分配给 ms 吗?
编辑:
针对帖子中留下的评论:
在发布这篇文章之前,我已经阅读了一些关于 C# 结构的教程,特别是本教程stack
使用这个词的次数多得我都懒得数了。这个MSDN 教程也谈到了堆栈,虽然它是 2003 年的,但我认为从那时起结构就没有改变。
我知道这可能与 C# 根本无关,但实际上是 JIT 编译器本身或 CLR 或其他我不知道的东西的问题。这就是我提出问题的目的,即了解更多有关 C# 内部工作原理的信息,即使这实际上与语言本身无关。
有C函数调用约定,对我的帖子最好的支持是这篇StackOverflow帖子。当我第一次在这里发布它时,我只是说出了我记得的内容,但由于 SO 答案说:
至于你的具体问题,这取决于ABI。有时如果返回值大于4字节但不大于8字节,可以分为EAX和EDX。但大多数时候,调用函数只会分配一些内存(通常在堆栈上)并将指向该区域的指针传递给被调用函数。
我在这一点上可能是错的,我说可能是,因为答案说通常。
我想了解如何处理结构的真正原因是因为我有一个项目,我必须多次读取串行端口以轮询数据,该数据将由方法返回。
由于数据只是一些字节,我认为我可以从结构中获得一些性能,而不是使用类来抽象串行端口传入的字节,但如果将作为堆分配return
传递,我对性能提高的期望可能是错误的struct
。
是的,我知道,我可以进行简单的测试并比较性能,但我想真正了解它在幕后是如何完成的,而不仅仅是记住模拟的结果。我喜欢知道我所使用的东西实际上是如何工作的,而不仅仅是学习如何使用它们。