2017-08-11 43 views
1

我有一個結構:在C中,ARM編譯器如何優化這個結構?

typedef struct mystruct_s { 
    uint8_t bufferA[1024]; 
    uint8_t bufferB[1024]; 
} mystruct; 

mystruct mystructA; 
mystruct mystructB; 

for(i = 0 ; i < 1024 ; i++) 
{ 
    mystructA.bufferA[i] = 0x01; 
    mystructA.bufferB[i] = 0x01; 
    mystructB.bufferA[i] = 0x01; 
} 

在我的節目,我曾訪問過的mystructA兩個緩衝成員,但只有在緩衝液A mystructB。

如果未訪問mystructB中的成員bufferB,編譯器會優化它以節省內存嗎?

我知道由於不同編譯器的性質,這可能看起來不明確。

例如,如果我在Keil下使用ARM C/C++編譯器爲STM32F4,它會做什麼?

+7

通過優化構建它,查看生成的代碼,您將看到編譯器實際執行的操作。 –

回答

2

如果未訪問mystructB中的成員bufferB,編譯器會優化它以節省內存嗎?

不,編譯器不允許更改結構的內存佈局。你已經告訴它保留1024字節,所以它必須這樣做。它不能「部分優化」一個結構:它必須優化整個結構分配或者什麼也不做。

這不是模棱兩可或系統相關的,所有的標準編譯器都必須這樣做。但是,mystructB.bufferB將包含垃圾值。


相關的優化:

一般來說,它是不是一個好主意,好幾個地方「觸摸」 RAM內存到處都是相同的循環中。在循環的每一圈,您讀取3個不相鄰的區域。這可能會阻止CPU有效地使用數據緩存,迫使它在循環的每一圈直接寫入RAM。

即使啓用了所有優化,編譯器通常也不會考慮數據高速緩存,因爲高速緩存內存的性質非常系統特定。

根據你的MCU的數據緩存是如何工作的,你可能實際上是能夠通過創造更多的環路,顯著提高性能:

for(i = 0 ; i < 1024 ; i++) 
    mystructA.bufferA[i] = 0x01; 
for(i = 0 ; i < 1024 ; i++) 
    mystructA.bufferB[i] = 0x01; 
for(i = 0 ; i < 1024 ; i++) 
    mystructB.bufferA[i] = 0x01; 

現在數據以線性順序訪問,這將導致最佳的高速緩存使用。循環的順序很重要,它應該與分配順序相同。

或者,由於您正在處理字節,因此請使用memset()。

+1

我覺得第一句話有點誤導;編譯器可以優化結構大小,只要它不改變程序的可觀察行爲。問題在於,發現這樣的優化是否可行,對於任何非平凡的程序來說都是非常困難的,因此編譯器甚至不會去嘗試。 – user694733

2

編譯器無法確定是否無法訪問特定的內存位置,因此它必須爲所有成員分配內存。

考慮這個例子*

memcpy(&mystructB.bufferA, &mystructA.bufferA, sizeof(mystructA)); 

即使只bufferA兩個struct s的使用,既bufferAbufferB被複制,所以內存必須有兩個。


*例說明了mystructB = mystructA的複雜的方式。爲了說明的目的,我以訪問structB的特定成員的方式構建示例,而不是structB本身。