2016-10-14 77 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

相關問題