據我所知,結構可以通過值作為引數傳遞,或者我們也可以使用指標通過參考傳遞它。
按值傳遞結構是否有效?如果我們有很多欄位的大結構,這似乎效率不高,因為結構資料被復制到函式的形式引數中,這涉及計算成本。
在這些情況下,通過參考傳遞結構似乎是一個更好的選擇。這有意義嗎?
另一個相關問題是編譯器是否在這個意義上進行優化,將按值傳遞的引數轉換為參考。
uj5u.com熱心網友回復:
如果結構很小,則按值傳遞。現代呼叫約定允許在合適的平臺上傳遞暫存器中的小結構。
如果結構很大,您可以定義例程以通過參考接收結構(使用指向const- 限定型別的指標)。
您還應該使用 , 宣告指標restrict,如const struct foo * restrict p. 否則,通過參考傳遞結構可能會影響優化。考慮傳遞const struct foo *p給一個也有引數struct foo *q或的例程float *f。在例程內部,如果代碼更改了指向q的結構或指向的結構,編譯器通常無法知道該指向的結構與指向結構的成員的 a 不同,或指向的結構不同。這可能導致編譯器在實際上沒有發生更改時多次重新加載資料。using告訴編譯器呼叫者不會傳遞floatfqpffloatppprestrictp這樣使用 via 的資料p也不會通過其他點在例程中使用。
另一個相關問題是編譯器是否在這個意義上進行優化,將按值傳遞的引數轉換為參考。
這并不常見。但是,通過參考回傳結構是常見的。呼叫約定通常是呼叫者為回傳的結構提供一個寫入位置,并將指向該結構的指標傳遞給源代碼。
uj5u.com熱心網友回復:
它肯定不會有效,但有時我們想處理本地自動變數。當您更改自動變數時,它將在函式回傳時停止存在,并且所有更改都將僅針對此區域變數進行。如果它是通過指標傳遞的,那么函式將修改原始物件,而不是本地物件。因此,編譯器不會對其進行優化。
typedef struct
{
double x[10000];
}big_struct;
void __attribute__((noinline)) foo(big_struct bs)
{
for(size_t i =0; i < sizeof(bs.x) / sizeof(bs.x[0]); i ) printf("%f\n", bs.x[i]);
}
void bar(void)
{
big_struct x;
/* some code */
foo(x);
}
.LC0:
.string "%f\n"
foo:
push rbp
push rbx
sub rsp, 8
lea rbx, [rsp 32]
lea rbp, [rsp 80032]
.L2:
movsd xmm0, QWORD PTR [rbx]
mov edi, OFFSET FLAT:.LC0
mov eax, 1
add rbx, 8
call printf
cmp rbx, rbp
jne .L2
add rsp, 8
pop rbx
pop rbp
ret
bar:
sub rsp, 160008
mov edx, 80000
lea rsi, [rsp 80000]
mov rdi, rsp
call memcpy
call foo
add rsp, 160008
ret
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506511.html
下一篇:如何在C中讀取記憶體區域
