鑒于我將在如下函式中回傳一個大結構:
#include <stdio.h>
// this is a large struct
struct my_struct {
int x[64];
int y[64];
int z[64];
};
struct my_struct get_my_struct_from_file(const char *filename) {
int tmp1, tmp2; // some tmp. variables
struct my_struct u;
// ... load values from filename ...
return u;
}
int main() {
struct my_struct res = get_my_struct_from_file("tmp.txt"); // <-- here
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
在由 標記的地方here,我是否必須假設這個大結構被復制,或者編譯器是否可能會做一些事情來避免這種情況?
謝謝
uj5u.com熱心網友回復:
...我是否必須假設這個大結構被復制......
不,您當然不必做出這樣的假設。沒有人要求您做出這種假設,而且將陳述句作為假設而不是從已知資訊(例如編譯器檔案或對生成的匯編代碼的檢查)中推匯出來是不明智的。
在您顯示的特定代碼中,好的編譯器很可能會進行優化,以便不會復制結構。(使用 Apple Clang 11 進行測驗證實它進行了這種優化。)但這可能是過于簡化的代碼。如果呼叫get_my_struct_from_file出現在與其定義分開的翻譯單元中,編譯器將不知道get_my_struct_from_file正在訪問什么。res在本例中,如果目標物件的地址先前已傳遞給某個其他翻譯單元中的某個其他例程,則編譯器無法知道其他例程沒有將地址存盤在某處并且get_my_struct_from_file沒有使用它。因此編譯器必須將回傳get_my_struct_from_file的結構和回傳值分配給的結構分開處理;它無法合并它們以避免復制。
為了確保編譯器做你想要的,簡單地告訴它你想要它做什么。撰寫代碼,以便函式將結果直接放入您要放入的結構中:
void get_my_struct_from_file(struct my_struct *result, const char *filename)
{
…
}
...
get_my_struct_from_file(&res, "tmp.txt");
uj5u.com熱心網友回復:
在由 標記的地方
here,我是否必須假設這個大結構被復制,或者編譯器是否可能會做一些事情來避免這種情況?
從語意上講,該結構從函式的區域變數復制到呼叫者的變數。這些是不同的物件,就像其他型別的物件一樣,將一個結構設定為另一個結構需要從一個表示復制到另一個表示。
避免復制的唯一方法是編譯器將區域變數視為呼叫者結構的別名,但在一般情況下這是錯誤的。這種混疊很容易產生明顯不同的行為。
有可能在某些特定情況下,編譯器確實可以避免復制,但是如果您想確保不發生復制,那么您應該明確設定所需的別名:
void get_my_struct_from_file(const char *filename, struct my_struct *u) {
int tmp1, tmp2; // some tmp. variables
// ... load values from filename into *u
}
int main() {
struct my_struct res = { 0 };
get_my_struct_from_file("tmp.txt", &res);
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/322590.html
上一篇:裸機STM32
