C 在循环内部或外部声明变量,会有很大的区别吗?

C 在循环内部或外部声明变量,会有很大的区别吗?,c,performance,variable-declaration,C,Performance,Variable Declaration,比如说 int i, a, c, d; // these vars will only be used in while while(bigNumber--) { i = doSomething(); // ** } 及 这对性能有很大影响吗?是的。变量i的范围在两种情况下都不同 在第一种情况下,我在一个块或函数中声明了一个变量。因此,您可以在块或函数中访问它 在第二种情况下,我在while循环中声明了一个变量。因此,您只能在while循环中访问它 这对性能有很大影响吗 否,

比如说

int i, a, c, d; // these vars will only be used in while
while(bigNumber--) {
    i = doSomething();
    // **

}


这对性能有很大影响吗?

是的。变量
i
的范围在两种情况下都不同

在第一种情况下,我在一个块或函数中声明了一个变量。因此,您可以在块或函数中访问它

在第二种情况下,我在while循环中声明了一个变量。因此,您只能在while循环中访问它

这对性能有很大影响吗

,从性能角度讲,您在哪里声明它并不重要

对于示例1:

int main()
{
    int i, bigNumber;

    while(bigNumber--) {
        i = 0;
    }
}
int main()
{
    int bigNumber;

    while(bigNumber--) {
        int i;
        i = 0;
    }
}
组件

main:
  push rbp
  mov rbp, rsp
.L3:
  mov eax, DWORD PTR [rbp-4]
  lea edx, [rax-1]
  mov DWORD PTR [rbp-4], edx
  test eax, eax
  setne al
  test al, al
  je .L2
  mov DWORD PTR [rbp-8], 0
  jmp .L3
.L2:
  mov eax, 0
  pop rbp
  ret
main:
  push rbp
  mov rbp, rsp
.L3:
  mov eax, DWORD PTR [rbp-4]
  lea edx, [rax-1]
  mov DWORD PTR [rbp-4], edx
  test eax, eax
  setne al
  test al, al
  je .L2
  mov DWORD PTR [rbp-8], 0
  jmp .L3
.L2:
  mov eax, 0
  pop rbp
  ret
示例2:

int main()
{
    int i, bigNumber;

    while(bigNumber--) {
        i = 0;
    }
}
int main()
{
    int bigNumber;

    while(bigNumber--) {
        int i;
        i = 0;
    }
}
组件

main:
  push rbp
  mov rbp, rsp
.L3:
  mov eax, DWORD PTR [rbp-4]
  lea edx, [rax-1]
  mov DWORD PTR [rbp-4], edx
  test eax, eax
  setne al
  test al, al
  je .L2
  mov DWORD PTR [rbp-8], 0
  jmp .L3
.L2:
  mov eax, 0
  pop rbp
  ret
main:
  push rbp
  mov rbp, rsp
.L3:
  mov eax, DWORD PTR [rbp-4]
  lea edx, [rax-1]
  mov DWORD PTR [rbp-4], edx
  test eax, eax
  setne al
  test al, al
  je .L2
  mov DWORD PTR [rbp-8], 0
  jmp .L3
.L2:
  mov eax, 0
  pop rbp
  ret

两者都生成相同的汇编代码。

这会产生不同……当你在循环外声明变量时,你可以在循环结束后得到它的值,但如果你在循环内声明它,你就不能在循环后使用它,因为它没有定义。

Q。它在性能方面会有很大的不同吗


A.根本没有性能差异。唯一的区别在于变量的范围是否在循环外部可见。

和I/O操作是最有价值的事情,您必须将其视为程序中的性能瓶颈。这两种代码之间没有性能差异。此外,编译器对代码进行了一些优化,如果这两个代码运行方式相同(即编译器自动将第二个代码转换为第一个代码),这并不意外。

我在汇编结果中看到的唯一区别是
movl$0,-4(%rbp)
指令的位置。理论上,如果代码使用的数据在内存中分布得更广,那么可能会对代码的性能造成影响(理论上,这会使代码的缓存不那么友好)

在实践中没有什么区别。缓存足够大,优化将使两个代码生成相同的程序集,并且很可能代码将被重新排序。下面是一个关闭和打开所有优化的简单测试用例

装配结果:

代码:

打开优化器将生成完全相同的结果:
我认为如果你这样说,它会不断地重新声明变量,因此无论你初始化什么,在变量重新声明之后,它都会丢失

while(bigNumber--) {
   int i, a, b, c; 
   i = doSomething();
}

好吧,你可以坐在板凳上。但是如果
doSomething
是一个大的过程,它将不可见difference@Jean-Françoisfafre——没有优化,GCC已经在一个小过程中生成了完全相同的代码。对于O2,它认为两个代码段是相同的(因此需要一个来完成其他的工作)。这取决于编译器将两者转换的方式,以及计算机在运行时优化的方式,因此不可能非常坚定地回答。无论如何,它不太可能观察到任何重大差异。@StoryTeller我误读了,我认为变量在一个案例中是全局的。好啊