为何非局部跳转中setjmp返回值不可赋值变量却能用于if判断?
为什么直接赋值setjmp返回值会失效,放到if里却可以?
这事儿核心是setjmp的特殊语义和编译器优化的冲突,得先搞懂setjmp到底是个啥东西:
- setjmp不是普通函数,第一次调用它会把当前程序上下文存在
env里,返回0; - 之后如果用
longjmp(env, val)跳回这个位置时,它会“假装自己刚被调用完”,返回你指定的val(必须非0)。
那第一种写法为啥不行?
当你写int value; value = setjmp(env);时,编译器会做常规优化——它默认认为一个函数调用只会执行一次,返回值也只会被赋值一次。所以可能会把value存在寄存器里,甚至直接把它当成常量0来处理。等你用longjmp跳回来的时候,这个value根本不会被更新成longjmp指定的返回值,代码逻辑直接崩了。
那第二种写法为啥没问题?
把setjmp(env)直接放在if的条件里,编译器会把这个调用的返回值当作需要实时判断的条件,知道这个值可能会被“二次修改”,所以不会随便优化掉。而且C标准本身也明确规定了,setjmp的合法调用场景就包括作为选择(if/switch)或迭代(while/for)语句的条件表达式,这种情况下编译器会保证返回值的正确性。
补充一句:如果非要用变量存返回值,也不是不行——把变量声明成volatile就行,比如volatile int value; value = setjmp(env);,volatile会告诉编译器“这个值可能会被意外修改”,不会做激进优化。
内容的提问来源于stack exchange,提问作者Musicminion
相关产品推荐
相关产品推荐

