volatile是通知编译器不要优化。这里有个例子volatile type qualifier - cppreference.com
#include <stdio.h>
#include <time.h>
int main(void)
{
clock_t t = clock();
double d = 0.0;
for (int n = 0; n < 10000; ++n)
for (int m = 0; m < 10000; ++m)
d += d * n * m; // reads from and writes to a non-volatile
printf("Modified a non-volatile variable 100m times. "
"Time used: %.2f seconds\n",
(double)(clock() - t)/CLOCKS_PER_SEC);
t = clock();
volatile double vd = 0.0;
//double vd = 0.0;
double prod;
for (int n = 0; n < 10000; ++n)
for (int m = 0; m < 10000; ++m) {
prod = vd * n * m; // reads from a volatile
vd += prod; // reads from and writes to a volatile
}
printf("Modified a volatile variable 100m times. "
"Time used: %.2f seconds\n",
(double)(clock() - t)/CLOCKS_PER_SEC);
}
在release模式下运行结果是:
Modified a non-volatile variable 100m times. Time used: 0.00 seconds
Modified a volatile variable 100m times. Time used: 0.40 seconds
反汇编后发现,第一个计算部分,直接被优化掉了。从5b9到5d7之间,没有乘加的运算。所以运行时间是零。改变循环次数,更能反应出优化的效果。
00000000000005a0 <main>:
5a0: 53 push %rbx
5a1: 48 83 ec 10 sub $0x10,%rsp
5a5: e8 c6 ff ff ff callq 570 <clock@plt>
5aa: 48 89 c3 mov %rax,%rbx
5ad: e8 be ff ff ff callq 570 <clock@plt>
5b2: 66 0f ef c0 pxor %xmm0,%xmm0
5b6: 48 29 d8 sub %rbx,%rax
5b9: 48 8d 35 58 02 00 00 lea 0x258(%rip),%rsi # 818 <_IO_stdin_used+0x8>
5c0: bf 01 00 00 00 mov $0x1,%edi
5c5: f2 48 0f 2a c0 cvtsi2sd %rax,%xmm0
5ca: b8 01 00 00 00 mov $0x1,%eax
5cf: f2 0f 5e 05 d1 02 00 divsd 0x2d1(%rip),%xmm0 # 8a8 <_IO_stdin_used+0x98>
5d6: 00
5d7: e8 a4 ff ff ff callq 580 <__printf_chk@plt>
5dc: e8 8f ff ff ff callq 570 <clock@plt>
5e1: 48 c7 44 24 08 00 00 movq $0x0,0x8(%rsp)
5e8: 00 00
5ea: 48 89 c3 mov %rax,%rbx
5ed: 31 d2 xor %edx,%edx
5ef: 90 nop
5f0: 66 0f ef db pxor %xmm3,%xmm3
5f4: 31 c0 xor %eax,%eax
5f6: f2 0f 2a da cvtsi2sd %edx,%xmm3
5fa: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
600: 66 0f ef d2 pxor %xmm2,%xmm2
604: f2 0f 10 44 24 08 movsd 0x8(%rsp),%xmm0
60a: f2 0f 10 4c 24 08 movsd 0x8(%rsp),%xmm1
610: f2 0f 2a d0 cvtsi2sd %eax,%xmm2
614: f2 0f 59 c3 mulsd %xmm3,%xmm0
618: 83 c0 01 add $0x1,%eax
61b: 3d 10 27 00 00 cmp $0x2710,%eax
620: f2 0f 59 c2 mulsd %xmm2,%xmm0
624: f2 0f 58 c1 addsd %xmm1,%xmm0
628: f2 0f 11 44 24 08 movsd %xmm0,0x8(%rsp)
62e: 75 d0 jne 600 <main+0x60>
630: 83 c2 01 add $0x1,%edx
633: 81 fa 10 27 00 00 cmp $0x2710,%edx
639: 75 b5 jne 5f0 <main+0x50>
63b: e8 30 ff ff ff callq 570 <clock@plt>
640: 66 0f ef c0 pxor %xmm0,%xmm0
644: 48 29 d8 sub %rbx,%rax
647: 48 8d 35 12 02 00 00 lea 0x212(%rip),%rsi # 860 <_IO_stdin_used+0x50>
64e: bf 01 00 00 00 mov $0x1,%edi
653: f2 48 0f 2a c0 cvtsi2sd %rax,%xmm0
658: b8 01 00 00 00 mov $0x1,%eax
65d: f2 0f 5e 05 43 02 00 divsd 0x243(%rip),%xmm0 # 8a8 <_IO_stdin_used+0x98>
664: 00
665: e8 16 ff ff ff callq 580 <__printf_chk@plt>
66a: 48 83 c4 10 add $0x10,%rsp
66e: 31 c0 xor %eax,%eax
670: 5b pop %rbx
671: c3 retq
672: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
679: 00 00 00
67c: 0f 1f 40 00 nopl 0x0(%rax)