是什么让 volatile 中断指针算术与结构?

What makes that volatile breaks pointer-arithmetic with structs?

在我们的代码中,我们使用指向结构的指针来扣除硬件寄存器的地址,以保持代码的可读性。

例如:

#include <cstdint>
#include <iostream>

struct reg {
    uint32_t t;
    uint32_t x;
    uint32_t value;
};

int main(void)
{
    struct reg *r = reinterpret_cast<struct reg *>(0x800000);

    std::cerr << &r->value << "\n";
    std::cerr << &r->t << "\n";
    std::cerr << &r->x << "\n";

    return 0;
}

硬件基地址为 0x800000,使用 writeReg(&t->x, 123); 将使其写入 0x800004。

一个 volatile-关键字被错误地放置在结构定义中:


struct reg {
    volatile uint32_t t;
    volatile uint32_t x;
    volatile uint32_t value;
};

现在发生的事情是所有字段都使用 &r->field-语法具有偏移量 1。

这里使用g++ (Debian 9.2.1-4) 9.2.1 20190821

使用 printf 和 C-style-cast 在 C 中重写测试,即使使用 volatile 也能再次给出正确的偏移量。

我无法理解为什么 volatile 关键字似乎破坏了指针算术?为什么?发生了什么事?

没有重载 operator<< 来打印指向 volatile 的指针。

您的编译器找到的最合适的重载是用于打印 bool 的重载,因此您的指针将转换为 bool

尝试:

std::cerr << (void *)&r->value << "\n";