2014-11-06 85 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祕密)