完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
volatile在词典中的意思是易变的,反复无常的。它在我们的程序设计中常常用到的。volatile是一个关键字,用来修饰一个变量,告诉编译器在编译的时候不要对其进行优化,在操作寄存器和多线程中这种用法是最常见的。
有这样一个例子: #include #include void my_func(); int? i; int main() { pthread_t my_thread; int err,k; if ((err = pthread_create(&my_thread,NULL,(void *)my_func,NULL)) perror(“can‘t create thread:%s/n”); i = 2; while(i == 2); printf(“main:%d/n”,i); while(1); return 0;? } void my_func() { sleep(1); i = 3; printf(“my_func:%d/n”,i); } 这个例子本意是想让主程序进入while(i == 2)这个循环,直到线程中将这变量i的值修改后跳出循环,可是结果是 my_func:3 这与想像中的结果完全不一样,是什么原因造成这样的结果呢?查看一下汇编代码,才知道,是编译器将这段代码给优化掉了,汇编代码如下: .file “test.c” .section .rodata.str1.1,“aMS”,@progbits,1 .LC0: .string “my_func:%d/n” .text .p2align 4,,15 .globl my_func .type my_func, @function my_func: pushl %ebp movl %esp, %ebp subl $8, %esp movl $1, (%esp) call sleep movl $3, 4(%esp) movl $.LC0, (%esp) movl $3, i call printf leave ret .size my_func, 。-my_func .section .rodata.str1.1 .LC1: .string “can’t create thread:%s/n” .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp leal -8(%ebp), %eax movl $0, 12(%esp) movl $my_func, 8(%esp) movl $0, 4(%esp) movl %eax, (%esp) call pthread_create testl %eax, %eax js .L9 .L4: movl $2, i .L6: jmp .L6 .L9: movl $.LC1, (%esp) call perror jmp .L4 .size main, 。-main .comm i,4,4 .ident “GCC: (GNU) 4.1.3 20080623 (prerelease) (Ubuntu 4.1.2-23ubuntu3)” .section .note.GNU-stack,“”,@progbits 在定义变量i的时候添加上volatile后: int volatile i; 的结果为: my_func:3 main:3 这个结果显然达到了我们预期的效果,再查看一下他的汇编代码,会看到那个带有条件的循环语句。 .file “test.c” .section .rodata.str1.1,“aMS”,@progbits,1 .LC0: .string “my_func:%d/n” .text .p2align 4,,15 .globl my_func .type my_func, @function my_func: pushl %ebp movl %esp, %ebp subl $8, %esp movl $1, (%esp) call sleep movl $3, i movl i, %eax movl $.LC0, (%esp) movl %eax, 4(%esp) call printf leave ret .size my_func, 。-my_func .section .rodata.str1.1 .LC1: .string “can‘t create thread:%s/n” .LC2: .string “main:%d/n” .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp leal -8(%ebp), %eax movl $0, 12(%esp) movl $my_func, 8(%esp) movl $0, 4(%esp) movl %eax, (%esp) call pthread_create testl %eax, %eax js .L13 .L4: movl $2, i .L6: movl i, %eax cmpl $2, %eax je .L6 mov i, %eax movl $.LC2, (%esp) movl %eax, 4(%esp) call printf .L8: jmp .L8 .L13: movl $.LC1, (%esp) call perror .p2align 4,,3 jmp .L4 .size main, 。-main .comm i,4,4 .ident “GCC: (GNU) 4.1.3 20080623 (prerelease) (Ubuntu 4.1.2-23ubuntu3)” .section .note.GNU-stack,“”,@progbits 比较红色部分就会看到是什么造成这种差异了! 为什么加上volatile和不加就有这么大的差距的,原因是每次使用变量都去内存中取值,然后通过系统总线传到CPU处理,会增加很大的开销,所以在CPU的cache中位变量啊做了一个副本,通过这个副本来进行赋值。在程序中首先对i 进行复制“i = 2”,然后又将i和2进行比较“i == 2”编译器认为i的值是2,没有变化,认为这个比较没有意义就将其优化掉了,将程序陷入无条件的死循环中,在线程my_func中修改i 的值夜就没有意义了,最终结果就是我么看到了那样了,加上volatile编译器就不会优化了,每次都被迫去内存中去取值,达到了我们预期的结果。 |
|
|
|
只有小组成员才能发言,加入小组>>
553个成员聚集在这个小组
加入小组12207 浏览 2 评论
4526 浏览 3 评论
3773 浏览 5 评论
9848 浏览 47 评论
4619 浏览 9 评论
786浏览 0评论
598浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-14 04:47 , Processed in 0.682826 second(s), Total 74, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号