首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将绝对地址转换为指针变量的现代C++方法是什么?

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

Stack Overflow用户
提问于 2017-09-20 17:16:49
回答 2查看 1.3K关注 0票数 17

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

代码语言:javascript
复制
#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(存储)是用一个4字节的偏移量和一条指令来完成的-同样是在我们的平台上。

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

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

在回应为什么要改变它的评论时:我担心这主要是为了名声和荣誉。但不仅仅是这样。有了这个C代码,调试可能会很困难。假设您想要记录所有的写访问,这种方法将要求您在任何地方重写所有内容。然而,在这里,我不是在寻找一个可以简化特定情况的解决方案,我是在寻找灵感。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-20 18:44:50

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

代码语言:javascript
复制
// 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);
}

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

票数 8
EN

Stack Overflow用户

发布于 2017-09-22 08:10:03

由于#define的唯一目的是使您能够访问结构成员,因此您可以使用模板来执行相同的操作。我的编译器为模板生成与#define相同的代码。

代码语言:javascript
复制
// #define hw_reg ((volatile struct regs *) hw_baseaddr)

template <class T, uintptr_t addr>
class RegsPtr
{
public:
  RegsPtr() { ; }
  volatile T* operator->() const { return reinterpret_cast<T*>(addr); }
  volatile T& operator*() const { return *operator->(); }
};

const RegsPtr<struct regs, hw_baseaddr> hw_reg;
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46317994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档