2012-08-14 69 views
1

假設我有一個這樣的結構:如何對待Ç結構分配

typedef struct { 
    char *str; 
    int len; 
} INS; 

這結構的數組。

INS *ins[N] = { &item, &item, ... } 

當我嘗試訪問它的元素,而不是指針,但結構本身,所有的字段被複制到一個臨時的地方的地方嗎?

for (int i = 0; i < N; i++) { 
    INS in = *ins[i]; 
    // internaly the above line would be like: 
    // in.str = ins[i]->str; 
    // in.len = ins[i]->len; 
} 

因此,當我增加結構域將是一個更昂貴的賦值操作?

回答

2

正確,in拷貝*ins[i]

不要介意你的內存消耗,但你的代碼將最有可能不正確:對象in模具在循環體的結束,您對in任何變化都沒有持久的效果!

+0

在問題中沒有跡象表明代碼將在創建後對「in」進行更改。定義'in'可能僅僅是訪問所需數組元素成員的便利。這將是完全有效的代碼。 – 2012-08-14 16:21:55

1

結構分配的行爲類似於memcpy。是的,對於較大的結構來說它更昂貴。矛盾的是,你的結構越大,測量增加另一個領域的額外費用就越困難。

1

是的,struct在C中具有value semantics。因此,將一個結構賦值給另一個結構將導致成員智能副本。請記住,指針仍然指向相同的對象。

1

編譯器可能優化掉結構的副本,而是直接從數組訪問成員以提供使用該副本的C代碼中所需的值,或者可能僅複製您使用的單個成員。一個好的編譯器會做到這一點。

通過指針存儲值可能會干擾此優化。例如,假設你的例程還有一個指向int的指針,p。當編譯器處理你的代碼INS in = *ins[i]時,它可以「思考」這樣的事情:「複製ins[i]是昂貴的。相反,我只記得in是一個副本,我將在稍後使用它時爲它取指令。「但是,如果您的代碼包含*p = 3,則可能會更改ins[i],除非編譯器能夠推斷出p不要指向ins[i]。 (有一種方法可以幫助編譯器使用關鍵字restrict進行推演。)

總結:表面看起來昂貴的操作可能會由一個好的編譯器高效地實現。看起來便宜的操作可能會很昂貴(寫入*p打破了一個很大的優化)。通常,您應該編寫明確表達算法的代碼,並讓編譯器進行優化。

展開編譯器如何優化它。假設你寫:

for (int i = 0; i < N; i++) { 
    INS in = *ins[i]; 
    ... 
} 

在代碼「...」訪問in.str和in.len但沒有任何其他的237名成員添加到INS結構。那麼編譯器是免費的,實際上,改變這個代碼爲:

for (int i = 0; i < N; i++) { 
    char *str = *ins[i].str; 
    int len = *ins[i].len; 
    ... 
} 

也就是說,即使你寫了,表面上,將所有的INS結構,編譯器只需要一份聲明覆制實際需要的部分。 (實際上,它甚至不需要複製這些部分,只需要生成一個程序得到相同的結果就好像它是直接跟在源代碼上的一樣)。