【发布时间】:2022-01-22 07:32:58
【问题描述】:
两个流行的编译器(gcc、clang)在以下函数的主体中发出存储指令:
void foo(char x) {
*(char *)0xE0000000 = x;
}
此程序可能在某些硬件架构上正常运行,其中写入的地址是内存映射 IO。
由于此访问是通过不限定为volatile 的指针执行的,编译器是否需要在此处发出存储?一个足够积极的优化器可以合法地消除这家商店吗?我很好奇这个商店是否对抽象机器构成了可观察到的副作用。
另外,C17 和 C++20 在这方面有区别吗?
【问题讨论】:
-
这取决于硬件以及编译器对底层硬件的理解程度。如果编译器已经编程有足够的知识,它知道地址没有任何特殊含义并且不会再次访问内存位置,那么肯定可以使用积极的优化来删除该代码。
-
取消引用未分配的内容是 C++ 中的 implementation defined。 AFAIK C++ 在您使用它的意义上没有地址的概念。使用
std::address_of返回T*。因此,您在这里使用的“地址”是一种实现方式。 -
C 标准不需要存储,因为分配给非易失性左值不是 C 标准定义的可观察行为。
-
@Jellyboy 这实际上是我很好奇的上下文,但我不想用这些细节污染问题。 :) 在我的情况下,它是一个带有内存映射外围 IO 系统的 ARM Cortex-M 系列微,我很好奇是否需要 volatile。
-
@CharlesNicholson 鉴于已定义实现,我会说 yes 因为如果您稍后升级编译器,它可能会死存储优化它或 UB 优化它。这两个都被
volatile阻止了。
标签: c++ c language-lawyer compiler-optimization