我有一个函数和几个嵌套循环。每个循环使用其他循环未使用的不同变量。
我的问题是出于优化考虑。
这是:哪种方法更好?
在循环体内定义局部变量
void aspProtocolDetectEvents()
{
uint8_t arrayIndex;
for( arrayIndex = 0; arrayIndex < sizeof(__aspProtocol_events); arrayIndex++ )
{
uint8_t contextBitPosition;
for(contextBitPosition = 0; __aspProtocol_events[arrayIndex] != 0; contextBitPosition++)
{
__aspProtocol_Event contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);
if( __aspProtocol_isRisenEvent(contextEvent) )
{
__aspProtocol_dispatchEvent(contextEvent);
__aspProtocol_clearEvent(contextEvent);
}
}
}
}
或者最好在函数体的开头定义所有这些吗?:
void aspProtocolDetectEvents()
{
uint8_t arrayIndex;
uint8_t contextBitPosition;
__aspProtocol_Event contextEvent;
for( arrayIndex = 0; arrayIndex < sizeof(__aspProtocol_events); arrayIndex++ )
{
for(contextBitPosition = 0; __aspProtocol_events[arrayIndex] != 0; contextBitPosition++)
{
contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);
if( __aspProtocol_isRisenEvent(contextEvent) )
{
__aspProtocol_dispatchEvent(contextEvent);
__aspProtocol_clearEvent(contextEvent);
}
}
}
}
我的意思是,我不知道编译器是否优化它。在代码结构方面,我更喜欢第一个例子,但如果需要更多时间(每次循环迭代时分配),我将不得不妥协,并使用第二个。
答案 0 :(得分:5)
因为他们是当地人,他们将被分配到堆栈。编译器将通过在调用函数时调整堆栈指针来确保它有足够的空间供所有本地人使用。
我不担心如何为嵌套作用域中的变量分配空间。如果您认为在使用范围内的本地人时遇到速度问题,那么请使用分析器进行测量,但我怀疑这是一个过早优化的经典案例。而是编写可读和可维护的代码。
答案 1 :(得分:1)
uint8_t contextBitPosition;
在大多数实现中,这在性能方面并不重要。鉴于此,如果您在尽可能最严格的范围内声明它,那将是最好的。
__aspProtocol_Event contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);
这很重要。如果此操作的结果始终相同,则没有理由将其放入循环中。你最好把它放在循环之外并计算一次结果。
虽然静态分析理论上可以解决这个问题并将其移出循环,但需要一个聪明的编译器。
答案 2 :(得分:1)
根据编译器的不同,编译器可能会重复使用堆栈空间。请考虑以下示例:
for (int i=0; i<somevalue; i++) {
for (int j=0; j<i; j++) {
int k[1024];
...
}
for (int j=0; j<i; j++) {
int k[1024];
...
}
}
在i
循环中,两个for循环的变量j
可以重用相同的堆栈空间,并且数组变量k
可以重用相同的堆栈空间。
所以没有性能改进,但可能有空间改进
答案 3 :(得分:0)
编译器可能会优化代码,以便所有变量都在函数代码中。如果它没有,则函数作用域更快,因为其他方面你会在循环的每次迭代中得到一个堆栈推送和弹出。但要考虑的是清晰度,而不是微观优化。
答案 4 :(得分:0)
当函数调用发生时,无论它们在何处定义,都会为其所有局部变量分配内存。所以它不会改变执行时间。在循环内部或外部定义局部变量只会改变它们的范围。(我的意思是,我们可以访问它们的范围)
阅读更多内容: journy to stack
答案 5 :(得分:0)
如果在本地范围内分配变量,源代码对性能没有任何影响。
如果使用变量,编译器将在第一次使用变量之前的某个时刻为变量分配空间。变量可能最终在CPU寄存器或堆栈中,或完全优化。