C11标准下编译器可否省略潜在无限循环及非volatile变量读取优化
问题解答
1. 编译器是否允许省略boo()函数内的while循环?
允许,完全符合你给出的C11条款的优化条件:
该条款的所有适用前提均已满足:
- while的控制表达式
v->cntr > 1不属于常量表达式 - 循环体为空,不存在任何输入输出操作
- 控制表达式仅访问普通非
volatile的结构体成员,无volatile对象访问、无同步操作、无原子操作
哪怕你认为v可能指向全局变量、可能被其他线程修改,这种情况在C11标准中属于数据竞争类未定义行为,编译器不需要考虑未定义行为的场景,完全可以依据该条款假定循环最终会终止,直接删除这个空循环,这也和条款脚注157的说明完全吻合。
2. 控制表达式中的v->cntr访问能否被认定为同步操作?
不能。
C11标准中定义的同步操作有明确的范围:仅包括互斥锁加解锁、原子变量的带内存序操作、线程创建/加入等明确的同步原语操作。普通非原子变量的读写不属于同步操作范畴,你预期其他线程修改普通变量的逻辑本身就不符合C11内存模型的线程安全要求,属于程序员自己引入的错误,标准不会将这类普通访问认定为同步操作。
3. 附加问题:v未定义为volatile时,编译器是否允许每次循环迭代不重新读取v->cntr的值?
允许。
对于非volatile、非原子的普通变量,C11标准允许编译器假定:在当前执行线程没有显式修改该变量的前提下,变量的值不会发生变化。你给出的循环内没有任何修改v->cntr的操作,编译器完全可以只在第一次判断前读取一次v->cntr的值存入寄存器,后续所有循环迭代都直接复用寄存器中的值判断,不需要重新访问内存。
内容的提问来源于stack exchange,提问作者Alex Lop.
相关产品推荐
相关产品推荐

