gpt4 book ai didi

c++ - 将绝对地址转换为指针变量的现代 C++ 方法是什么?

转载 作者:IT老高 更新时间:2023-10-28 22:21:33 25 4
gpt4 key购买 nike

在嵌入式世界中,人们将硬件(-配置)-寄存器-映射写成结构,这是一个非常简单的 32 位硬件示例:

#define hw_baseaddr ((uintptr_t) 0x10000000)

struct regs {
uint32_t reg1;
uint32_t reg2;
};

#define hw_reg ((volatile struct regs *) hw_baseaddr)

void f(void)
{
hw_reg->reg1 = 0xdeadcafe;
hw_reg->reg2 = 0xc0fefe;
}

这很好用,编译器(至少在我们的平台上是 gcc)识别出 hw_reg正在引用相同的地址(在编译时已知且不变)并且是 ld 'ing 它只有一次。第二个st (store) 是通过一条指令以 4 字节偏移量完成的 - 再次在我们的平台上。

如何在不使用 #defines 的情况下使用现代 C++(C++11 后)重现此行为?

我们尝试了很多东西:static const内外类和constexpr .他们都不喜欢(隐式)reinterprest_cast<>的。

回应关于为什么要更改它的评论:恐怕这主要是名誉和荣耀。但不仅如此。使用此 C 代码调试可能会很困难。想象一下,您想要记录所有写访问,这种方法将要求您在任何地方重写所有内容。但是,在这里我不是在寻找可以简化特定情况的解决方案,而是在寻找灵感。

编辑 只是为了根据一些评论澄清:我问这个问题不要更改任何有效的代码(并且是在 1990 年代编写的)。我正在为 future 的项目寻找解决方案,因为我对 define 并不完全满意-实现,并在问自己现代 C++ 是否有更好的可能性。

最佳答案

我认为变量模板在这里是一个优雅的解决方案。

// Include this in some common header
template <class Impl>
volatile Impl& regs = *reinterpret_cast<volatile Impl*>(Impl::base_address);

template <std::uintptr_t BaseAddress>
struct HardwareAt {
static const std::uintptr_t base_address = BaseAddress;

// can't be instantiated
~HardwareAt() = delete;
};

// This goes in a certain HW module's header
struct MyHW : HardwareAt<0x10000000> {
std::uint32_t in;
std::uint32_t out;
};

// Example usage
int main()
{
std::printf("%p\n%p\n", &regs<MyHW>.in, &regs<MyHW>.out);

// or with alias for backward compatibility:
auto hw_reg = &regs<MyHW>;
std::printf("%p\n%p\n", &hw_reg->in, &hw_reg->out);
}

像这样使用它而不是使用宏的一个好处是,您的类型是安全的,而且您实际上可以从同一个源文件中引用不同硬件模块的寄存器,而不会混淆它们。

关于c++ - 将绝对地址转换为指针变量的现代 C++ 方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46317994/

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