【发布时间】:2022-01-07 22:32:09
【问题描述】:
假设以下代码
struct a {
unsigned cntr;
};
void boo(struct a *v) {
v->cntr++;
while(v->cntr > 1);
}
由于C11标准中的以下语句,我想知道是否允许编译器省略boo()内的while循环:
控制表达式不是常量表达式的迭代语句,156) 不执行输入/输出操作,不访问 volatile 对象,并且在其主体中不执行同步或原子操作,控制表达式,或者(在 for 语句的情况下)它的表达式 3,可以被实现假定为终止。157)
157)这旨在允许编译器转换,例如即使在无法证明终止时也可以删除空循环。
v->cntr 在控制表达式中是否可以被视为一个同步,因为v 可能是指向可以在外部修改的全局结构的指针(例如由另一个线程)?
附加问题。
如果v 未定义为volatile,是否允许编译器在每次迭代时不重新读取v->cntr?
【问题讨论】:
-
be considered as a synchronization since v may be a pointer to a global structure which can be modified externally这是一个标准,它都是定义的,同步操作是定义的——像在你的代码中修改一个全局变量不是同步操作。 -
@KamilCuk 在一个或多个内存位置上的同步操作是获取操作、释放操作、获取和释放操作或消耗操作。 - I找不到consume operation的定义,但是为什么不能将读取全局内存视为
consume operation? -
编译器可以为所欲为,只要可观察到的结果与在抽象 C 机器上执行的程序相同。
-
couldn't find the definition of consume operationFor memory_order_consume, a load operation performs a consume operationport70.net/~nsz/c/c11/n1570.html#7.17.3p5 -
@tstanisl 这在这种情况下正好相反,因为我希望一旦
v->cntr达到大于 1 的值,流就会停止/挂起。在此处描述的情况下,流将永远不会停止,因为编译器可能会丢弃整个while循环
标签: c language-lawyer infinite-loop c11