我发现自己想要编写一个既可以在 volatile 内存块上又可以在非 volatile 内存块上运行的例程。类似的东西:
void byte_swap (unsigned * block_start, size_t amount) {
for (unsigned * lp = block_start; lp < block_start + amount; lp++) {
*lp = htonl(*lp);
}
memcpy (block_start, some_other_address, amount);
}
(不是我的真实代码,而是示例)。
我遇到的问题是,如果我尝试使用指向 volatile 内存区域的指针,编译器会提示丢失了 volatile 限定符。我可以放弃 volatile,但如果它试图缓存更改(或以前的读取),这似乎会使例程本身变得不安全,不是吗?
另一种选择是使例程本身采用 unsigned volatile *
,但这需要我将所有非 volatile 调用者转换为 volatile 指针。
我想第三种选择是制作两个完全相同的例程,区别仅在于是否出现 volatile
关键字。太糟糕了。
是否有正确的方法来处理这个问题,如果有的话是什么?
作为一个最相关的问题,预定义例程(特别是 memcpy)是否可以安全地与 volatile 指针一起使用?如果我这样做了,会有什么不好的事情发生在我身上?仅仅因为它不使用 volatile void 指针而不得不自己重新滚动任何与内存相关的库例程似乎有点愚蠢。
最佳答案
只有在处理内存映射 IO 时才需要使用 volatile
,也就是说,连续读取或写入同一内存地址可以而且应该返回不同的值。如果您写入的内容相当于简单的共享内存,那么分配访问 CPU 或硬件设备(例如 DMA Controller )的简单正式切换机制就足够了。
还要注意,在非缓存内存上执行操作,或者更糟糕的是,在内存映射设备上执行操作会非常慢。在执行任何字节交换操作之前复制到正常的未缓存内存可能会好得多。将大量数据复制到内存映射 IO 时,DMA 可以为您节省大量 CPU 周期。
volatile
往往会成为编译器优化的障碍,应在必要时避免。
关于c++ - 定义用于 volatile 和非 volatile 对象的例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3526423/