为什么C中的静态局部变量重新加载?

时间:2016-10-14 22:20:07

标签: c compilation

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

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

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:0)

可以同时从不同的线程调用

a_proc_s。在这种情况下,如果它被另一个线程递增(并且你使增量成为原子),你可能会期望使用不同的a_var值。