2012-09-05 63 views
2

根據維基百科的網站:爲什麼'volatile'沒有區別?

http://en.wikipedia.org/wiki/Volatile_variable

我抄襲了它的示例代碼在我的筆記本電腦的測試,但兩人都沒有什麼區別!這裏是我的GCC版本信息:

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00) 
Copyright (C) 2007 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

的C源代碼是

/* volatile_var.c */ 
#include <stdio.h> 
int main() { 
     /* in no_volatile_var.c there is no volatile here */ 
     volatile int a = 10, b = 100, c = 0, d = 0; 
     printf("%d\n", a + b); 

     a = b; 
     c = b; 
     d = b; 

     printf("%d\n", c + d); 
     printf("%d\n", a); 
     return 0; 
} 

我編譯no_volatile_var.c和volatile_var.c都與

gcc -S *.c 

,但出來的是以下同樣

.section __TEXT,__text,regular,pure_instructions 
    .globl _main 
    .align 4, 0x90 
_main: 
Leh_func_begin1: 
    pushq %rbp 
Ltmp0: 
    movq %rsp, %rbp 
Ltmp1: 
    subq $32, %rsp 
Ltmp2: 
    movl $10, -12(%rbp) 
    movl $100, -16(%rbp) 
    movl $0, -20(%rbp) 
    movl $0, -24(%rbp) 
    movl -12(%rbp), %eax 
    movl -16(%rbp), %ecx 
    addl %ecx, %eax 
    xorb %cl, %cl 
    leaq L_.str(%rip), %rdx 
    movq %rdx, %rdi 
    movl %eax, %esi 
    movb %cl, %al 
    callq _printf 
    movl -16(%rbp), %ecx 
    movl %ecx, -12(%rbp) 
    movl -16(%rbp), %ecx 
    movl %ecx, -20(%rbp) 
    movl -16(%rbp), %ecx 
    movl %ecx, -24(%rbp) 
    movl -20(%rbp), %ecx 
    movl -24(%rbp), %edx 
    addl %edx, %ecx 
    xorb %dl, %dl 
    leaq L_.str(%rip), %rdi 
    movl %ecx, %esi 
    movb %dl, %al 
    callq _printf 
    movl -12(%rbp), %ecx 
    xorb %dl, %dl 
    leaq L_.str(%rip), %rdi 
    movl %ecx, %esi 
    movb %dl, %al 
    callq _printf 
    movl $0, -8(%rbp) 
    movl -8(%rbp), %eax 
    movl %eax, -4(%rbp) 
    movl -4(%rbp), %eax 
    addq $32, %rsp 
    popq %rbp 
    ret 
Leh_func_end1: 

    .section __TEXT,__cstring,cstring_literals 
L_.str: 
    .asciz "%d\n" 

    .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 
EH_frame0: 
Lsection_eh_frame: 
Leh_frame_common: 
Lset0 = Leh_frame_common_end-Leh_frame_common_begin 
    .long Lset0 
Leh_frame_common_begin: 
    .long 0 
    .byte 1 
    .asciz "zR" 
    .byte 1 
    .byte 120 
    .byte 16 
    .byte 1 
    .byte 16 
    .byte 12 
    .byte 7 
    .byte 8 
    .byte 144 
    .byte 1 
    .align 3 
Leh_frame_common_end: 
    .globl _main.eh 
_main.eh: 
Lset1 = Leh_frame_end1-Leh_frame_begin1 
    .long Lset1 
Leh_frame_begin1: 
Lset2 = Leh_frame_begin1-Leh_frame_common 
    .long Lset2 
Ltmp3: 
    .quad Leh_func_begin1-Ltmp3 
Lset3 = Leh_func_end1-Leh_func_begin1 
    .quad Lset3 
    .byte 0 
    .byte 4 
Lset4 = Ltmp0-Leh_func_begin1 
    .long Lset4 
    .byte 14 
    .byte 16 
    .byte 134 
    .byte 2 
    .byte 4 
Lset5 = Ltmp1-Ltmp0 
    .long Lset5 
    .byte 13 
    .byte 6 
    .align 3 
Leh_frame_end1: 


.subsections_via_symbols 

根據Wiki的解釋,應該有差異,易失版本應該比不易變版本更大。我將它們編譯爲二進制文件,並發現其大小也相同。

問題:?

  • 請問我LLVM-GCC原因在於(後者我將測試在Linux上,這些代碼)或Wiki的的解釋是錯誤?
  • 它們都編譯相同的二進制代碼(只是根據它們的大小),所以它們的打印結果是相同的。但根據Wiki的解釋,這兩個打印不同的屏幕輸出?

更新

這個問題是由於維基百科上關於優化設置錯誤,並有標題說的沒有關聯。我應該關閉這個問題嗎?

+0

禁用優化並嘗試。 – asawyer

+4

嘗試使用gcc -O3並參見 –

+0

@asawyer:''''volatile關鍵字會阻止編譯器執行優化' – perilbrain

回答

5

使用gcc -O3打開優化,您應該看到有所不同。

4

volatile關鍵字僅僅是編譯器的一個提示,即外部線程可能隨時更改此變量,因此應該謹慎對待依賴於不會發生這種情況的優化。但是你的應用程序沒有任何其他線程,所以沒有理由以不同的方式對待它。

您可以嘗試使用更高優化設置(-O3命令行參數)編譯程序 - 這可能會導致編譯器對非易失性版本進行優化,這些版本對於易失性版本是被禁止的。

0

如果我們將變量聲明爲volatile,編譯器將無法執行優化。