簡體   English   中英

當函數調用的結果初始化堆棧變量時,是否復制結構?

[英]Is a struct copied when a stack-variable is initialized by a result of a function call?

鑒於我將在如下函數中返回一個大結構:

#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標記的here ,我是否必須假設這個大型結構已被復制,或者編譯器是否可能會采取某些措施來避免這種情況?

謝謝

...我是否必須假設這個大結構被復制......

不,您當然不必做出這樣的假設。 沒有人要求您做出這種假設,而且將語句作為假設而不是從已知信息(例如編譯器文檔或對生成的匯編代碼的檢查)中推導出來是不明智的。

在您顯示的特定代碼中,好的編譯器很可能會進行優化,以便不會復制結構。 (使用 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");

here標記的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 ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM