C++ 在ARM体系结构中,C函数如何返回大于一个字的值
在C程序中,内存布局由.BSS、.DATA、.TEXT、堆和堆栈组成。当一个函数返回的值小于一个字时,它将进入R0寄存器,但如果返回值大于一个字,它将通过内存返回。例如:C++ 在ARM体系结构中,C函数如何返回大于一个字的值,c++,c,arm,C++,C,Arm,在C程序中,内存布局由.BSS、.DATA、.TEXT、堆和堆栈组成。当一个函数返回的值小于一个字时,它将进入R0寄存器,但如果返回值大于一个字,它将通过内存返回。例如: LargeType t; t = func(arg); 其实施方式如下: LargeType t; (void) func(&t,arg); 我的问题是编译器使用哪部分内存来超过“t”?调用func(&t,arg)将继续并用所需的值填充t的内存地址。因此t必须在调用方函数的堆栈上分配(除非您想动态分配t,如t=ma
LargeType t;
t = func(arg);
其实施方式如下:
LargeType t;
(void) func(&t,arg);
我的问题是编译器使用哪部分内存来超过“t”?调用func(&t,arg)将继续并用所需的值填充t的内存地址。因此t必须在调用方函数的堆栈上分配(除非您想动态分配t,如t=malloc(sizeof(LargeType)),它将在堆上)。不确定编译器在这里要做什么
/* Caller function */
...
LargeType t; /* Allocated on caller's stack */
LargeType *t = malloc(sizeof(LargeType)); /* Allocation on heap */
(void) func(&t, arg); /* Fills up t with required value */
除异常外,基本上使用了In + C++ ABI。在这种ABI中,按值返回大型对象的调用约定是调用方传递一个隐藏指针,函数使用该指针在return语句中创建对象。这就是返回值优化的实现方式
现在,你提供的翻译是不正确的。开始时使用的代码使用分配而不是初始化:LargeType t;
t = func(arg);
编译器完成的翻译相当于:
LargeType t;
LargeType __tmp;
func(&__tmp,arg);
t.operator=(__tmp);
__tmp.~LargeType();
临时变量将在堆栈中创建,地址传递给将使用它创建对象的函数。然后赋值将发生,并在完整表达式的末尾t=func(arg)代码>临时文件将被销毁
将其与初始化情况进行比较:
LargeType t = func(arg);
在这种情况下,编译器可以执行您提到的转换,转换后的代码将是:
LargeType t;
func(&t,arg);
非常重要的区别在于初始化和赋值是完全不同的操作。在初始化的情况下,对象变成了,什么都没有,现在有了。在赋值的情况下,对象已经存在,它有一个状态,并且它可能正在管理资源。如果允许您建议的转换,则此代码将泄漏内存:
struct Test {
int *p; // assume other members make this object large
Test() : p(new int()) {}
Test(int i) : p(new int) { *p = i; }
Test(Test const & other) : p(new int) { *p = other->p; }
~Test() { delete p; }
Test& operator=(Test const & other) { *p = other->p; }
};
Test f(int arg) {
return Test(1)
}
Test t;
t = f(5);
转换后的代码可能泄漏的地方:
Test t; // allocates a pointer
f(&t, 5); // expands to:
// __ret->p = new int; // leak!
// *(__ret->p) = 5;
“当一个函数返回的值小于一个字时,它将进入R1寄存器”你的意思是r0
?你基本上没有回答你自己的问题,因为它被实现为func(&t,arg)代码>-在这种情况下,调用者管理内存并只传入指向该内存的指针-即,它与函数的任何其他参数一样。但是,如果代码是C++,而不是C,那么它的代码分配的复杂程度就更高了。