问题:
写了这么一个程序来测试longjmp对于变量值的影响
按照书上说的,声明为volatile的变量的值应该不变(那句话本身就有点歧义,我也不知道是不是这么理解,所以写了这么一个程序),而一般int的值则是未定义的,大家解释一下我的程序输出吧,说说volatile到底是什么语义?
#include <unistd.h>
#include <setjmp.h>
#include <sys/types.h>
int main()
{
volatile int i = 5;
int j = 9;
jmp_buf jmp;
if(setjmp(jmp) == 0)
{
printf("set jump\n");
i++;j++;
printf("first: i = %d,j = %d\n",i,j);
}
else
{
printf("now: i = %d,j = %d\n",i,j);
return 1;
}
longjmp(jmp,1);
return 0;
}
回答:
这个输出是6,10,而变量值不可变,这个应该是const提供的语义吧
lz对volatie的意思基本上理解反了 volatie的本意就是易变,反复无常的
它的意思是,告诉编译器我是易变的,可能在一些特殊情况下(调试,中断或者其他地方)会把我改变,
这样结果会阻止一些编译器的优化,比如对于内存里的值可能避免直接的从寄存器读取缓存值,变量消除
又试了下 这个结果的确是不确定的,g++ 加上优化-O结果是6 10 6 9 普通的编译后结果是6 10 6 10。
auto变量不一定就是在寄存器里,不加优化它一般在栈里。加了优化后,这个结果是6 9的原因,也不是它在寄存器里。看汇编结果,-O的时候把j的地址分配直接延后了,它在{}里才去计算j的值,所以在第一个{}里压的j是10,也就是把j++这步直接优化掉了,而在第二个{}里压的j是9,所以第二次输出的是9。也就是说它并没有意识到第一个{}里会改变j的值这种情况,而还是把初值9入栈。
还有些问题可能会有疑问:volatile变量一定在内存上吗?这个没发现标准里有明确的规定。自动变量何时会在寄存器?何时又必须放到栈上呢?
这个程序的解释可以再参考下:
http://www.9php.com/FAQ/cxsjl/c/2008/08/1223954127528.html
再看volatile的语义:
ISO C standrd
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine,as described in 5.1.2.3.Furthermore, at every sequence point the value last stored in the
object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously. What constitutes an access to an object that has volatile-qualified type is implementation-defined.
ISO C++
[Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C + + as they are in C. ]
【 在 yiyemengzhou 的大作中提到: 】
: 刚试了下,确实是6、10,把刚才的帖子删了
: 不过我觉得第二次的输出应该是6、9
: volatile意思是易变的,那么每次就应该从内存里面去吧
: 每次修改和改变都会反映到内存上,
: 而变量j是auto的,也就是寄存器里面的值
: 这时候setjmp的时候应该保存起来
: longjmp的时候应该恢复成9才对
: 至于i,就不能恢复了。。。