如何在C++中将指针初始化为特定的内存地址

13

关于这个问题的有趣讨论可以在这里找到,但是至今没有人能提供C++的解决方法:

#include <stdio.h>

int main(void)
{
  int* address = (int *)0x604769; 
  printf("Memory address is: 0x%p\n", address);

  *address = 0xdead; 
  printf("Content of the address is: 0x%p\n", *address);

  return 0;
}

在C++中最合适的做法是什么?


3
除了改用C++语法之外,实际上你在C++中的操作方法并没有真正的区别。 - CashCow
5个回答

33
在C++中,始终优先使用reinterpret_cast而不是C-cast。它非常丑陋,以至于有人会立即发现存在的危险。
示例:
int* ptr = reinterpret_cast<int*>(0x12345678);

那东西刺痛了我的眼睛,但我喜欢它。


2
示例代码是用C编写的,OP知道这一点。他想知道在C++中是否有更好的方法来完成相同的操作。在设备驱动程序中,您可能会知道要写入的绝对地址。我记得在使用MS-DOS时曾经做过这种事情,直接写入内存屏幕。当然,这是通过宏实现的。 - CashCow
2
通过地址访问硬件寄存器在嵌入式系统中是常见的做法。它们可以定义为常量指针或使用 #define 声明。 - Thomas Matthews
1
你为什么要去使用 void*?OP的代码需要一个指向 int 的指针。 - John Dibling
2
@CashCow:当然可以 - 但无论如何,您都在进行特定于实现的转换,而reinterpret_cast是C++中执行此操作的方式。它更好,因为更容易找到,并且如果有人尝试移植这个操作,它会标记为潜在的不安全操作。 - David Thornley
@Coincoin 如果地址已经被占用怎么办? - Lokanath
显示剩余2条评论

2

目前没有标准且可移植的方法来实现。不可移植的方法可能包括reinterpret_cast(表示地址的某些整数)。


1

这将有效:

void *address=(void *) 0xdead; // But as mentioned, it's non-standard

address=(void *) 0xdeadbeef; // Some other address

1
如果问题是“什么是C++的方式”,那么你选择使用void*只会让糟糕的情况变得更糟。 - John Dibling
不要理会他们,void*由于恐惧而被低估了,哈哈。从某种意义上说,这是一种纯粹的答案。 - That Realty Programmer Guy

1
在C++中,我更喜欢在头文件中将指针声明为常量指针:
volatile uint8_t * const UART_STATUS_REGISTER = (uint8_t *) 0xFFFF4000;

在C语言中,通常使用宏来实现这一点:
#define UART_STATUS_REGISTER ((volatile uint8_t * const) 0xFFFF4000)

在源代码的其余部分中,内存地址通过符号名称引用。

1
我想补充一点,如果你想在指定地址分配对象时调用其构造函数,可以调用 new 的放置运算符:
int *pLoc = reinterpret_cast<int*>(0x604769);
int *address = new (pLoc) int (1234); // init to a value

这也用于内存缓存对象。创建一个缓冲区,然后将对象分配给它。

unsigned char *pBuf = new unsigned char[sizeof(CMyObject) + alignment_size];
allign_buf(pBuf);
CMyObject *pMyObj = new (pBuf) CMyObject;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接