是什么让 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";
在我们的代码中,我们使用指向结构的指针来扣除硬件寄存器的地址,以保持代码的可读性。
例如:
#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";