gpt4 book ai didi

c - 强制读取 volatile 变量

转载 作者:太空狗 更新时间:2023-10-29 17:23:33 25 4
gpt4 key购买 nike

我正在处理的一个嵌入式项目需要读取内存中的特定位置,但不需要该内存位置的值。目前,我正在将 volatile 变量读入虚拟变量,如下面的 foo1() 所示,但我对 foo2() 中的方法感到好奇。

void foo1(void) {
volatile uint32_t *a = (volatile uint32_t *)0xdeadbeef;
volatile uint32_t discard = *a;
}
void foo2(void) {
volatile uint32_t *a = (volatile uint32_t *)0xdeadbeef;
*a;
}

查看反汇编(使用 gcc 4.7.2 和 -O3 编译):

  foo1:
movl 0xdeadbeef, %eax
movl %eax, -0x4(%rsp)
ret
foo2:
movl 0xdeadbeef, %eax
ret

foo2() 中的方法似乎有效,但我想知道它是否一定有效,并且不是我正在使用的编译器版本和优化的副作用。

最佳答案

关键字 volatile 告诉编译器一个对象可能会在正常(即编译器可见)程序流的范围之外发生变化。因此,编译器performs此访问一般。最后一句是指如何执行访问,例如字节读取、未对齐读取等

此外,编译器必须按照程序流给定的顺序执行对此类对象的所有访问。但是请注意,它可能会自由地重新排序对非 volatile 对象的访问,并且底层硬件也可能认为不同(编译器可能不知道)。

编译器可能仍会优化对 volatile 对象的访问,这些对象仅在可见代码中存在并被修改。对于未获取地址的局部变量(可能还有其他情况),这是正确的,因为无法在范围之外访问这些变量。对于您使用的指针,这是不正确的,因为编译器不知道它们指向的对象。

要在没有编译器警告的情况下删除表达式的结果,只需将其转换为 void:

volatile uint32_t *vi = ...;
(void)*vi; // this still might be optimized if vi is local

(如果目标是只读的,添加const。)

参见 gcc documentation有关 volatile 访问的详细信息。符合 C 标准的实现必须提供此信息。

另请注意,底层硬件仍可能对访问进行重新排序,除非内存区域使用严格排序/非缓存访问策略。这是典型的内存映射外设寄存器。如果使用缓存/MMU,则可能必须相应地设置这些区域。

关于c - 强制读取 volatile 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34521620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com