2011-08-10 21 views
1

我有一個函數,我正在訪問一個結構的成員很多次。 我在想什麼是這樣的好習慣?在函數中使用結構

例如:

struct s 
{ 
    int x; 
    int y; 
} 

和我已經爲使用malloc該結構體10級的對象分配的存儲器。因此,無論何時只需要使用函數中的一個對象,我通常會創建(或傳遞爲參數)指針並將其指向所需的對象(我的上級告訴我要避免數組索引,因爲它會添加訪問結構中的任何成員時的計算)

但這是正確的方法嗎?我知道解引用並不像創建副本那麼昂貴,但是如果我在函數中多次解引用(如20到30),該怎麼辦?

如果我爲結構變量創建臨時變量(只有我需要的,我當然不使用所有成員)並且複製該值,然後在返回之前設置實際結構的值,會更好嗎?

此外,這是不必要的微型優化?請注意,這是針對嵌入式設備的。

+2

嘗試這兩個,和_measure_他們執行得如何。 – Mat

回答

2

首先,索引一個數組並不是很昂貴(只有一個操作比一個指針取消引用更昂貴,或者有時候沒有,這取決於情況)。其次,大多數編譯器在按值返回結構時將執行所謂的RVO或返回值優化。這是調用者爲其調用的函數的返回值分配空間的地方,並且祕密地​​將該內存的地址傳遞給它使用的函數,結果是沒有製作副本。爲此,它會自動地,所以

struct mystruct blah = func(); 

只有構建一個對象,將其傳遞到FUNC爲它透明地使用程序員,並沒有複製需要做。

我不知道是什麼,如果你分配一個數組索引函數的返回值,就像這樣:

someArray[0] = func(); 

將在編譯過程的someArray[0]地址並做RVO這樣,還是會只是不做這種優化?你必須得到一個更有經驗的程序員來回答這個問題。我猜想編譯器雖然足夠聰明,但它只是一個猜測。

是的,我會稱之爲微型優化。但我們是C程序員。和that's how we roll

1

通常情況下,您想在C中創建一個傳遞結構的副本的情況是,如果您想操作數據。也就是說,你的更改不會反映在struct it self中,而只是返回值中。至於哪個更昂貴,這取決於很多事情。其中許多將實施改爲實施,所以我需要更具體的信息才能更有幫助。不過,我認爲,在嵌入式環境中,你的內存比你的處理能力要高。真的這看起來像不必要的微型優化,你的編譯器應該處理它。

+0

我想改變函數中實際struct對象的值(即讓它反映在結構本身上),這就是我問這個問題的原因。否則,使用指針可能比創建副本和使用更多內存更好。是的,它感覺像微型優化,但我的上司告訴我這樣做。嘿嘿 –

0

在這種情況下,在堆棧上創建臨時變量會更快。但是,如果你的結構更大,那麼你可能會更好地解除引用。

3

這是針對嵌入式系統的。所以,我不能對編譯器會做什麼做任何假設。我不能對字的大小,寄存器的數量或者訪問堆棧的成本做任何假設,因爲你沒有告訴我這個架構是什麼。我曾經在8080s上做過嵌入代碼時,他們是新的...

好吧,那該怎麼辦?

選擇一段真實的代碼並對其進行編碼。按照上面列出的每種不同方式對其進行編碼。編譯它。找到強制它打印出生成的彙編代碼的編譯器選項。用每一組不同的優化選項編譯每段代碼。抓住處理器的參考手冊並計算每種情況下使用的週期。

現在您將獲得有關基於哪個決策的真實數據。真實的數據比一百萬高度體驗專家程序員的意見要好得多。與你的主要程序員坐下來,向他展示代碼和數據。他可能會向你展示更好的編碼方式。如果是這樣,重新編碼它,編譯它,並計算他的代碼使用的週期。告訴他他的方式如何解決。

在最糟糕的情況下,您將花上一個週末來學習一些關於編譯器工作方式的重要內容。您將會檢查N種方式來編碼M次不同的優化選項。您將學到很多關於機器指令集的知識。你將會知道編譯器有多好或壞。你將有機會更好地瞭解你的主要程序員。而且,你將獲得真實的數據。

真實數據是您必須回答此問題所需的那種數據。除了這些數據之外,沒有人告訴你只是基於自我的猜測。數據回答了這個問題。

鮑勃彭德爾頓