volatile实例
来源:互联网 发布:windows snmp工具 编辑:程序博客网 时间:2024/06/05 14:31
volatile实例
一、volatile的汇编解释
main.c:
优化要开得比较高,gcc -O2 -S main.c得到
cmpl $100, a //先比较a和100
je .L4 //相等就跳到L4
..........
ret
.L4:
jmp .L4 //L4再跳到L4,就是把和a比较的部分给删了,来了死循环,因为编译器认定了a不会变
..........
.data
.align 4
.type a, @object
.size a, 4
a:
.long 100
加上了volatile int a = 100就变成了:
.L3:
movl a, %eax
cmpl $100, %eax
je .L3
也是个一直从L3调回L3的过程,但是L3本身包括了对a是否等于100的验证。
总之,volatile至少一点效果是告诉编译器,这个变量别去乱优化,不像你想象的那样。
二、volatile实用举例
对于一中的int a,怎么都想不到要变的方法。改一下就可以了:
gcc -O2 main.c之后执行,kill -SIGUSR1 进程号是没有用的,就像之前说的已经优化成死循环了,改成volatile int a就可以了。
另一个简单的共享内存例子:
汇编代码为:
........
movb $1, (%eax)
.L2:
jmp .L2 //有是自己跳回自己,根本就没有去看*pc的值
........
改下代码得到个反例:
像预想的那样,非volatile的-O2完全就优化成了死循环,而volatile的则在子进程打印后父进程打印(当然具体退出时间前后不一定)。
总之,编译器往往“聪明反被聪明误”,像上面的a和*pc都是对程序员可预期会变的,但是编译器看不出来,这时就要用volatile明确地告知。
一、volatile的汇编解释
main.c:
#include <stdio.h>int a = 100;void main(){ while(a == 100){} printf("finally...\n");}
优化要开得比较高,gcc -O2 -S main.c得到
cmpl $100, a //先比较a和100
je .L4 //相等就跳到L4
..........
ret
.L4:
jmp .L4 //L4再跳到L4,就是把和a比较的部分给删了,来了死循环,因为编译器认定了a不会变
..........
.data
.align 4
.type a, @object
.size a, 4
a:
.long 100
加上了volatile int a = 100就变成了:
.L3:
movl a, %eax
cmpl $100, %eax
je .L3
也是个一直从L3调回L3的过程,但是L3本身包括了对a是否等于100的验证。
总之,volatile至少一点效果是告诉编译器,这个变量别去乱优化,不像你想象的那样。
二、volatile实用举例
对于一中的int a,怎么都想不到要变的方法。改一下就可以了:
#include <stdio.h>#include <signal.h>int a = 100;void handler(int num){ a = 200;}void main(){ signal(SIGUSR1,handler); while(a == 100){} printf("finally...\n");}
gcc -O2 main.c之后执行,kill -SIGUSR1 进程号是没有用的,就像之前说的已经优化成死循环了,改成volatile int a就可以了。
另一个简单的共享内存例子:
//仅作为演示用,异常情况未作处理#include <sys/shm.h>#include <stdio.h>int main(){ int shmid = shmget(1234,sizeof(char),0666|IPC_CREAT); void *shm = shmat(shmid,NULL,0); char *pc = shm; *pc = 1; while(*pc){} printf("finally"); shmdt(shm);}
汇编代码为:
........
movb $1, (%eax)
.L2:
jmp .L2 //有是自己跳回自己,根本就没有去看*pc的值
........
改下代码得到个反例:
//仅作为演示用,异常情况未作处理#include <sys/shm.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){ int shmid = shmget(1234,sizeof(char),0666|IPC_CREAT); //共享内存相关函数不多,用法也方便,不熟悉百度也能两下上手 if(fork() == 0){ //子进程 sleep(10); //休息十秒好看打印结果 void *shm = shmat(shmid,NULL,0); //子进程能从副进程出继承到变量的值,并且往往是写时才复制 char *pc = shm; *pc = 0; printf("son:done\n"); //改完了,打印done shmdt(shm); exit(0); } void *shm = shmat(shmid,NULL,0); //不在这之后fork是shm返回的线性地址空间子进程和父进程完全是两码事 char *pc = shm; //volatile char *pc = shm; *pc = 1; while(*pc){} printf("finally"); shmdt(shm);}
像预想的那样,非volatile的-O2完全就优化成了死循环,而volatile的则在子进程打印后父进程打印(当然具体退出时间前后不一定)。
总之,编译器往往“聪明反被聪明误”,像上面的a和*pc都是对程序员可预期会变的,但是编译器看不出来,这时就要用volatile明确地告知。
阅读全文
0 0
- volatile实例
- volatile 实例讲解
- Java volatile关键字实例
- 通过实例理解:C语言 volatile 关键字
- volatile
- volatile
- Volatile
- volatile
- volatile
- volatile
- volatile
- volatile
- volatile
- Volatile
- volatile
- volatile
- volatile
- volatile
- html通过自适应制作手机端音乐播放器
- 阿里云发送短信验证码
- shell 脚本 测试webApp
- TCP流式套接字与I/O复用Select模型代码
- script标签的type="test/html"时
- volatile实例
- 齐次变换
- spring mvc leaning
- chrome 调试工具的使用
- Linux 下wifi 驱动开发(一)—— WiFi基础知识解析
- $ each() 小结
- js 中 的 if使用条件
- js 闭包 理解 copy
- android 开机向导OOBE源码分析