有点奇怪的C++;代码 对不起,如果这很简单,我的C++是生锈的。

有点奇怪的C++;代码 对不起,如果这很简单,我的C++是生锈的。,c++,c,embedded,C++,C,Embedded,这是干什么的?据我所知,没有赋值或函数调用。这个代码模式在我继承的一些代码中重复了很多次。如果重要的话,那就是嵌入式代码 *(volatile UINT16 *)&someVar->something; 编辑:从那里继续,下面的附加代码是否证实了希思的怀疑?(完全源于代码,包括重复,但名称已更改以保护无辜者除外) 我认为作者的意图是使编译器在这些点上发出内存障碍。通过评估volatile的表达式结果,编译器得到的指示是,不应优化此表达式,而应在出现此惯用法的每一行“实例化”访问v

这是干什么的?据我所知,没有赋值或函数调用。这个代码模式在我继承的一些代码中重复了很多次。如果重要的话,那就是嵌入式代码

*(volatile UINT16 *)&someVar->something;
编辑:从那里继续,下面的附加代码是否证实了希思的怀疑?(完全源于代码,包括重复,但名称已更改以保护无辜者除外)


我认为作者的意图是使编译器在这些点上发出内存障碍。通过评估volatile的表达式结果,编译器得到的指示是,不应优化此表达式,而应在出现此惯用法的每一行“实例化”访问volatile位置的语义(内存障碍、优化限制)

这种类型的习惯用法可以“封装”在预处理器宏(
#define
)中,以防另一个编译以不同的方式产生相同的效果。例如,能够直接对读或写内存屏障进行编码的编译器可能使用内置机制,而不是这种习惯用法。在宏中实现这种类型的代码可以在整个代码库中更改方法

编辑:用户sharth有一个很好的观点,即如果此代码在指针地址是物理地址而不是虚拟地址(或映射到特定物理地址的虚拟地址)的环境中运行,则执行此读取操作可能会导致在外围设备上执行某些操作。

因此,这是一个很难解决的问题


如果该地址指向FPGA或其他设备上的内存映射区域,那么当您读取该地址时,该设备实际上可能正在执行某些操作。

通常这是错误代码

<> P> C和C++的挥发性很小,不提供内隐记忆障碍。因此,这段代码完全是错误的,因为它是按照

memory_barrier();
*(volatile UINT16 *)&someVar->something;
这只是一个糟糕的代码

排除:
易失性
不会使变量原子化

在本文中:


这就是为什么
volatile
几乎不应该在正确的代码中使用。

这是嵌入式编程中一个相当常见的习惯用法(尽管它应该封装在一组函数或宏中),其中需要访问设备寄存器。在许多体系结构中,设备寄存器被映射到内存地址,并像任何其他变量一样被访问(尽管是在固定地址-可以使用指针,或者链接器或编译器扩展可以帮助固定地址)。但是,如果C编译器没有看到变量访问的副作用,它可以对其进行优化—除非变量(或用于访问变量的指针)标记为volatile

因此,表达方式

*(volatile UINT16 *)&someVar->something;
将从存储在
someVar
指针中的地址在某个偏移量(由
something
结构元素的偏移量提供)处发出16位读取。由于
volatile
关键字,此读取将发生,并且编译器无法对其进行优化

请注意,一些设备寄存器执行某些功能,即使它们只是被读取-即使数据读取不是以其他方式使用。这在状态寄存器中非常常见,在状态寄存器中,在读取指示特定位中错误状态的寄存器后,可能会清除错误条件


这可能是使用
volatile
关键字的一个更常见的原因。

此外,宏可以使正在发生的事情更加明显。。。(#定义读取#内存#屏障…)第一步应该是评估它是否确实创建了内存屏障。这似乎是我们的意图,但许多平台上的易失性变量只是相对于其他易失性变量排序的。即使它适用于这个嵌入式平台,也可能不适用于其他平台;我会寻找一个更好、更便携的解决方案来创建屏障。我不认为它与内存屏障有任何关系,它是一个嵌入式平台,它可能会将一个变量映射到某个IO。在嵌入式系统中,您的编辑更可能是解释(如标签所示),即使我理解了第一个答案,我也会说不太可能。嵌入式代码?然后,正如sharth所怀疑的,这可能是一个物理地址。注意,我在下面的回答中添加了一个指向文章的链接:最好使用
(void)
,强制转换读取结果,以避免编译器警告。所以
(void)*(volatile uint16\u t*)&someVar->something
。当然,将其包装在宏或内联函数中,不要到处剪切和粘贴!为什么是远射?我认为这是一个完全合乎逻辑的解释+1原始问题缺乏很多澄清,无法清楚地说明这是在嵌入式系统上发生的,等等。谢谢,我将此问题标记为答案,因为我认为这是最清楚、最完整的回答。
*(volatile UINT16 *)&someVar->something;