C编译器可以优化由挥发性指针变量指向的值吗?
在这里,指针是挥发性的,而不是指向的值:
int* volatile ptr;
这里指向的值是挥发性的,而不是指针:
volatile int* p;
这两者都是挥发性的:
volatile int* volatile ptr;
在第一种情况下,指针是波动的,编译器可以优化指向指向的值吗?
知道我们也可以同时拥有指针和价值挥发性,这使我认为编译器可以优化只有指针挥发时指向的值。 这是真的吗? 是否有任何好的应用程序或很好的示例可能需要?
Here the pointer is volatile, not the value that is pointed to:
int* volatile ptr;
Here the value that is pointed to is volatile, not the pointer:
volatile int* p;
Here both are volatile:
volatile int* volatile ptr;
In the first case where the pointer is volatile can the compiler optimize the value pointed?
Knowing that we can also have both pointer and value volatile makes me think that the compiler may optimize the value that is pointed to when only the pointer is volatile.
Is this true?
Is there any good application or good example where this may be required?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
考虑此代码:
编译器无法优化第二个
printf
使用与第一个printf
使用相同的参数。如果ptr
更改了,它必须通过访问ptr
来重新计算参数。考虑此代码:
编译器可以优化第二个
printf
使用与第一个printf
的参数,因为它们都使用非挥发性x
。x
的值以前是从挥发性指针中得出的事实是无关紧要的。Consider this code:
The compiler cannot optimize the second
printf
to use the same argument as the firstprintf
. It must recompute the argument by accessingptr
, in caseptr
changed.Consider this code:
The compiler can optimize the second
printf
to use the same argument as the firstprintf
, because they both use the non-volatilex
. The fact that the value ofx
was previously derived from a volatile pointer is irrelevant.通过“优化”,我带您意思是避免从主内存中读取。原则上,是的,如果是指向非易失性对象的挥发性指针,则可以完成。必须读取指针值,但是实现可以测试新读值的值,以决定是否需要从内存读取指向对象。
但是,在实践中,这种方法可能比无条件地从内存中进行读取更为昂贵,因此我不希望C实现以这种方式“优化”。
有点见上文。
挥发性
不是抑制优化作为目标本身。它是关于指导编译器的对象的性质和使用,以使实施不会做出错误的假设。如果指针的存储可能会在程序自己的C语言语义范围之外进行更改,则应将其声明为
volatile
。如果指针的值可能指向受此类更改的对象,则指向键入的对象应为volatile
。如果两者,则两者兼而有之。在实践中,需要一个指针来挥发数据,但需要挥发性指针极为罕见。By "optimize", I take you to mean avoiding a read from main memory. In principle, yes, that can be done in the case of a volatile pointer to a non-volatile object. The pointer value must be read, but the implementation could test that freshly-read value to decide whether it needs to read the pointed-to object from memory.
In practice, however, such an approach is likely to be more costly than just performing the read from memory unconditionally, so I do not expect C implementations to "optimize" in such a way.
Sort of. See above.
volatile
is not about suppressing optimization as a goal in itself. It is about instructing the compiler about the nature and use of an object, so that the implementation does not make faulty assumptions.If the storage of the pointer is subject to change outside the scope of the program's own C-language semantics, then it should be declared
volatile
. If the pointer's value may point to an object that is subject to such changes then the pointed to type should bevolatile
. If both, then both. In practice, it is merely uncommon to require a pointer to volatile data, but exceedingly rare to require a volatile pointer.从理论上讲,可以例如,如果它可以扣除尖头值与其他一些非合格指针所指向的值相同。
实际上,您如何在未知地址中优化某些东西?编译器必须以某种方式知道上次访问的特定地址存储的内容。通过挥发性指针的每个访问都涉及阅读该指针。
同样,不合格的指针不能别名
*volatile
指针,因为您永远无法假设它们指向相同的地址。volatile
用于指针的大部分是有意义的,如果硬件寄存器又包含另一个寄存器的地址。但是这些极少数情况将是挥发性类型*挥发性
风味,或更可能挥发性uint32_t*
,然后将其删除以获取整数,而整数又转换了挥发性UINT32_T*
如果需要,指针。我不记得曾经使用
type* volatile
或挥发性类型* volatile
在任何现实世界中如果在任何地方,最有可能遇到这种情况。In theory it could, for example if it can deduct that the pointed-at value is the same as pointed at by some other non-qualified pointer.
In practice, how do you optimize something at an unknown address? The compiler would have to somehow know what was in stored at that specific address the last time it was accessed. Each access through the volatile pointer involves reading that pointer.
Similarly, non-qualified pointers cannot alias
*volatile
pointers, because you can never assume that they point at the same address.volatile
for pointers mostly makes sense in case of hardware registers that in turn contain an address to another register. But those rare cases would be of thevolatile type* volatile
flavour, or more likelyvolatile uint32_t*
which is then de-referenced to get an integer, which in turn is converted to avolatile uint32_t*
pointer if needed.I can't recall ever using
type* volatile
orvolatile type* volatile
in any real-world system, and then I mostly program the kind of low level drivers where you would be most likely to encounter such, if anywhere.考虑此代码:
编译器需要生成读取
p
两次的代码,但是它只需要放弃p
计算x
。y
是一个死亡值,可以消除,以及计算它所需的解除。live demo (稍微修改以使跟踪消除更加容易)。
Consider this code:
The compiler needs to generate code for reading
p
twice, but it only needs to dereferencep
once to computex
.y
is a dead value and can be eliminated, together with the dereference needed to compute it.Live demo (slightly modified to make keeping track of the dereference easier).