找回密码
 欢迎注册
查看: 17355|回复: 15

[提问] volatile 可以用来修饰函数返回值吗

[复制链接]
发表于 2011-5-10 13:13:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
如题,可否举一个例子
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-5-10 13:59:30 | 显示全部楼层
such as
  1. volatile int volatileFun(void)
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-5-10 21:42:00 | 显示全部楼层
百度了一下,“volatile的变量是说这变量可能会被意想不到地改变”  我个人理解是对它的访问不做优化,对内存变量才有效,应该是编译器级别的约定(又如static 的变量会被解释成全局变量)。
函数的返回值在eax中,将忽略volatile。

小例:均启用/Ox优化
  1. #include <stdio.h>
  2. volatile int myfun(int n)
  3. {
  4.     n=n+2;
  5.    
  6.     return rand(n);
  7. }
  8. void main()
  9. {
  10.     volatile  int i=10;
  11.     //int i=10;
  12.     int a,b,c;
  13.     a=i;
  14.     b=i;
  15.     c=i;
  16.     printf("i=%d\n",a);
  17.     printf("i=%d\n",myfun(4));
  18. }
复制代码
片段:
  1. mov         DWORD PTR _i$[esp+4], 10  //i

  2. mov         eax, DWORD PTR _i\$[esp+4] //a
  3. mov         ecx, DWORD PTR _i\$[esp+4] //b
  4. mov         edx, DWORD PTR _i\$[esp+4] //c
复制代码
四次访存,未优化。
若改为 int i=10;则有
  a=i;
    b=i;
    c=i;
因未实际使用,已全被忽略。


以上对于函数返回值加与不加无影响,均为
push          eax
push         OFFSET    \$SG2233
call         _printf

总之,volatile 针对存变量,每次访存的话就不一定保存数据一致性了,且volatile  会影响全局优化。
有误之处请指正,也是才接触,似乎面试中常考,解释的也很玄。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-5-11 08:10:54 | 显示全部楼层
我也Google了下,结论是:volatile 可以用来修饰函数返回值。

volatile的本意是“易变的” 由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。


在linux的source code(linux/mm/memory.c)中有这样两句:
  1. volatile void do_exit(long code);
  2. static inline volatile void oom(void)
  3. {
  4.     printk("out of memory\n\r");
  5.     do_exit(SIGSEGV);
  6. }
复制代码
volatile修饰函数是为了线程安全的考虑。

volatile 函数 是特指存在于volatile memory当中的函数吧,函数指针也是随时会变化的。

限定词volatile告诉编译器“不知道何时会改变”,防止编译器依据变量的稳定性作任何优化。当读在代码控制之外的某个值时,例如读一块通信硬件中的寄存器,将使用这个关键字。无论何时需要volatile变量的值,都能读到,即使在该行之前刚刚读过。

“在代码的控制之外”的某个存储空间的一个特殊例子是在多线程程序中。如果正在观察被另一个线程或进程修改的特殊标识符,这个标识符应该是volatile的,所以编译器不会认为它能够对标识符的多次读入进行优化。

注意当编译器不进行优化时,volatile可能不起作用,但是当开始优化代码时(当编译器开始寻找冗余的读入时),可以防止出现重大错误。

volatile的语法与const一样,但volatile的意思是“在编译器认识的范围外,这个数据可以改变”。就像建立const对象一样,程序员也可以建立volatile对象,甚至可以建立const volatile对象,这个对象不能被客户程序员改变,但可通过外部的代理程序改变。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-5-11 09:32:48 | 显示全部楼层
有人写了这样的测试例子:
  1. volatile int volatileFun(void)
  2. {
  3.     printf("\n In volatileFun");
  4.     return 0;
  5. }
复制代码
我想其初衷就是防止该函数被优化掉了吧.
不知道编译器会对该函数具体作何种优化
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-5-11 09:34:45 | 显示全部楼层
4# gxqcn
static inline volatile void oom(void)

这个太强悍了,
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-5-11 10:02:06 | 显示全部楼层
很想看看 linux/mm/memory.c,但没下载到。
就是想了解下用 volatile 修饰函数返回值的目的:真是声明该函数指针可能被更改吗?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-5-11 10:04:15 | 显示全部楼层
7# gxqcn
是不是 允许被线程更改
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-5-11 10:12:02 | 显示全部楼层
volatile 修饰的目的是防止编译器优化,通知它是个可变的变量,主要来自其它线程的修改。
但用它来修饰 函数,我还没用过。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-5-11 10:12:15 | 显示全部楼层
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-27 17:32 , Processed in 0.045741 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表