C 在循环内定义的局部变量

C 在循环内定义的局部变量,c,C,我有一个函数和几个嵌套循环。每个循环使用其他循环未使用的不同变量 我的问题是出于优化考虑 问题是:哪种方法更好 在循环体中定义局部变量的步骤 void aspProtocolDetectEvents() { uint8_t arrayIndex; for( arrayIndex = 0; arrayIndex < sizeof(__aspProtocol_events); arrayIndex++ ) { uint8_t contextBitPosi

我有一个函数和几个嵌套循环。每个循环使用其他循环未使用的不同变量

我的问题是出于优化考虑

问题是:哪种方法更好

在循环体中定义局部变量的步骤

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=0;arrayIndex
还是最好在函数体的开头这样定义它们

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);
            }
        }
    }
}
void aspProtocolDetectEvents()
{
uint8_t阵列索引;
uint8_t contextBitPosition;
__aspProtocol_事件contextEvent;
对于(arrayIndex=0;arrayIndex

我的意思是,我不知道编译器是否优化了它。在代码结构方面,我更喜欢第一个例子,但如果它需要更多的时间(每次循环迭代时分配),我将不得不妥协,使用第二个

编译器可能会优化代码,使所有变量都在函数代码中。否则,函数作用域会更快,因为从另一个角度看,在循环的每次迭代中都会得到堆栈推送和弹出。但考虑因素应该是清晰,而不是微观优化

uint8_t contextBitPosition;
在大多数实现中,就性能而言,这并不重要。有鉴于此,最好是在尽可能严格的范围内声明它


这很重要。如果此操作的结果始终相同,则没有理由将其放入循环中。你最好把它放在循环之外,然后计算一次结果


虽然静态分析可以从理论上解决这个问题,并将其移出循环,但这需要一个聪明的编译器。

因为它们是局部变量,所以会在堆栈上进行分配。编译器将在调用函数时调整堆栈指针,以确保它有足够的空间容纳所有局部变量


我不担心如何为嵌套作用域中的变量分配空间。如果您认为在使用作用域局部变量时发现了速度问题,那么可以使用探查器进行测量,但我怀疑担心这是一个典型的过早优化案例。而是编写可读和可维护的代码。

根据编译器的不同,编译器可能会重复使用堆栈空间。考虑下面的例子:

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];
        ...
    }
}

for(int i=0;i当函数调用发生时,内存被分配给它的所有局部变量,不管它们定义在哪里。因此它不会改变执行时间。在循环内部或外部定义局部变量只会改变它们的作用域。(我的意思是,我们可以访问它们的作用域)

更多信息请访问:

在本地范围内分配变量的源代码对性能没有任何影响


编译器将在第一次使用变量之前的某个时间为变量分配空间。该变量可能会在CPU寄存器或堆栈中结束,或者完全优化。

探查器说了什么?@SouravGhosh抱歉,什么是探查器?您应该查看生成的汇编程序。Optimizer可以执行以下操作:gics..如果使用第一种方法,不会花费太多时间,这完全取决于编译器优化,在编译两种方法后,您可以查看汇编代码。可能的重复实际上取决于优化器配置。“每次迭代时,您都会得到堆栈推送和弹出”-不,这并不一定意味着这一点。实现可以预先计算和分配所需的堆栈帧一次。唯一的区别是在哪个循环中使用了堆栈指针的哪些偏移。“函数范围”并不意味着你认为它可以做什么。在C中,“函数范围”指的是标签和goto。最好不要使用这个术语。
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];
        ...
    }
}