2016-10-14 48 views
0

我发现了一个关于局部静态变量的有趣行为。编译器每次都尝试重新加载它们。以下是代码示例。为什么C中的静态局部变量重载?

extern void extern_proc(int a, int b); 
void a_proc_s() { 
    static int a_var = 0; 
    a_var++; 
    extern_proc(a_var, 1); 
    extern_proc(a_var, 2); 
    extern_proc(a_var, 3); 
    extern_proc(a_var, 4); 
    extern_proc(a_var, 5); 
    extern_proc(a_var, 6); 
} 
void a_proc_r() { 
    static int a_var = 0; 
    register int r_var = ++a_var; 
    extern_proc(r_var, 1); 
    extern_proc(r_var, 2); 
    extern_proc(r_var, 3); 
    extern_proc(r_var, 4); 
    extern_proc(r_var, 5); 
    extern_proc(r_var, 6); 
} 

功能a_proc_s将尝试从内存中加载a_var每次调用extern_proc。函数a_proc_r将使用来自寄存器的本地副本。 为什么编译器不能在前一个函数中优化这个负载?

下面是来自x86_64汇编程序的有趣片段。其他架构类似。

;Fragment for a_proc_s 
movl a_proc_s.a_var(%rip), %edi 
movl $2, %esi 
callq extern_proc 
movl a_proc_s.a_var(%rip), %edi 
movl $3, %esi 
callq extern_proc 

;Fragment for a_proc_r 
movl $2, %esi 
movl %ebx, %edi 
callq extern_proc 
movl $3, %esi 
movl %ebx, %edi 
callq extern_proc 

GCC Explorer

回答

5

编译器无法确保extern_proc永远不会调用a_proc_s修改静态变量。

0

a_proc_s可能同时从不同的线程调用。在这种情况下,如果它被另一个线程增加(你会使增量为原子的),你可能会预期使用不同的值a_var

+1

如果没有线程特定的结构,来自不同线程的调用是未定义的行为。编译器可能会忽略它们。 – Michas

相关问题