2017-08-11 44 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本身。