2014-11-06 84 views
0

C编译器如何传递并从函数返回struct/union?在函数调用之前,结构是否被推入堆栈,只有传递给该函数的结构引用?将struct/union传递给C中的函数C

同样的问题适用于退货。函数返回的是什么?

typedef struct { 
    long m4; 
    long m3; 
    long m2; 
    long m1; 
} ext_components_t; 

typedef union { 
    long array[sizeof(int_components_t)]; 
    int_components_t comp; 
} int_components_u; 

typedef union { 
    long array[sizeof(ext_components_t)]; 
    ext_components_t comp; 
} ext_components_u; 

#pragma never_inline 
ext_components_u transfer(int_components_u m) 
{ 
    ext_components_u out; 
    out.comp.m1 = 10*m.comp.a+11*m.comp.b+12*m.comp.c; 
    out.comp.m2 = 20*m.comp.a+21*m.comp.b+22*m.comp.c; 
    out.comp.m3 = 30*m.comp.a+31*m.comp.b+32*m.comp.c; 
    out.comp.m4 = 40*m.comp.a+41*m.comp.b+42*m.comp.c; 
    return out; 
} 

volatile int_components_u x; 
volatile ext_components_u y; 
void main() 
{ 
    y = transfer(x); 
} 

这是我的猜测(伪代码):

push_stack(x.array[0]) 
push_stack(x.array[1]) 
push_stack(x.array[2]) 

call transfer 

y.array[0] = shift_stack() 
y.array[1] = shift_stack() 
y.array[2] = shift_stack() 
y.array[3] = shift_stack() 

或者另一种解决方案可能是:

call transfer(&x) 
y.array[0] = shift_stack() 
y.array[1] = shift_stack() 
y.array[2] = shift_stack() 
y.array[3] = shift_stack() 
+0

它取决于实现。通常实施将遵循平台ABI。 – 2014-11-06 09:11:44

回答

6

在C函数所有的参数都是按值传递。这意味着结构和联合在传递给函数时是复制。如何处理复制是特定于实现的,但最常见的方法是在堆栈上分配空间并将结构/联合的内容复制到该空间中。

返回数据也是如此,它是通过值(即复制)返回的。


这里有一个重要的事情要注意,那就是C没有通过引用传递。当你传递一个指针时,它是按值传递的指针,即它被复制。

但是,您可以使用指向的指针来模拟传递引用。

+3

这不是普遍的情况。标准中没有任何内容要求结构和联合在栈上传递。 ABI可以允许它们通过寄存器传递。 – 2014-11-06 09:13:02

+0

@DavidHeffernan你是对的,更新了答案。 – 2014-11-06 09:14:41

+1

@DavidHeffernan我敢肯定,标准中没有任何规定甚至存在一个堆栈。 :) – unwind 2014-11-06 09:35:49

2

如何传递结构并返回结构依赖于实现。通常它们被复制到堆栈中。尽可能将参数传递到寄存器(为了速度)。

一个实现可能以不同的方式传递一个int和一个只包含int成员的结构体。同样的规则也适用于工会。

有些书说“通过将参数从右到左推送到堆栈上来传递参数”。这是过于简单。 (来自彼得范德林登的Expert C编程深C秘密)