C11 - 编译器忽略潜在的无限循环

Ale*_*op. 2 c infinite-loop language-lawyer c11

假设以下代码

struct a {
    unsigned cntr;
};

void boo(struct a *v) {
    v->cntr++;
    while(v->cntr > 1);
}
Run Code Online (Sandbox Code Playgroud)

我想知道由于C11标准中的以下语句,是否允许编译器省略while内部循环:boo()

控制表达式不是常量表达式的迭代语句,156)不执行输入/输出操作,不访问易失性对象,并且在其主体、控制表达式中不执行同步或原子操作,或者(在 for 的情况下)语句)其表达式-3,可以假定由实现终止。157)


157)这是为了允许编译器进行转换,例如即使无法证明终止也可以删除空循环。

在控制表达式中,是否可以v->cntr将 视为同步,因为v可能是指向可以在外部修改(例如由另一个线程)的全局结构的指针?

附加问题。如果未定义为,是否允许编译器v->cntr在每次迭代时不重新读取?vvolatile

Kam*_*Cuk 5

控制表达式中的 v->cntr 是否可以被视为同步

不。

来自https://port70.net/~nsz/c/c11/n1570.html#5.1.2.4p5

该库定义了许多原子操作(7.17)和互斥体上的操作(7.26.4),这些操作被专门标识为同步操作。

所以基本上,函数 fromstdatomic.hmtx_*fromthread.h都是同步操作。

因为 v 可能是指向可以在外部修改的全局结构的指针(例如由另一个线程)?

不要紧。对我来说,假设听起来像是它们不允许许多理智的优化,我不希望我的编译器做出这样的假设。

如果v在另一个线程中进行修改,那么它将不排序,这只会导致未定义的行为https://port70.net/~nsz/c/c11/n1570.html#5.1.2.4p25

如果 v 未定义为 易失性,是否允许编译器在每次迭代时不重新读取 v->cntr?

是的。