13

An interesting discussion about this started here but no one have been able to provide the C++ way of doing:

#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;
}

What is the most appropriate way of doing such a thing in C++?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • 3
    Apart from changing to C++ constructs, there is no real difference to the way you would do it in C++. – CashCow Oct 14 '10 at 15:50

5 Answers5

32

In C++, always prefer reinterpret_cast over a C-cast. It's so butt ugly that someone will immediately spot the danger.

Example:

int* ptr = reinterpret_cast<int*>(0x12345678);

That thing hurts my eyes, and I like it.

Coincoin
  • 27,880
  • 7
  • 55
  • 76
  • 2
    The sample code is in C and the OP knows it is. He is asking if there is a better way to do the same in C++. In a device driver you may well know the absolute address you wish to write to. I remember doing this kind of thing in my early days with MS-DOS to write directly to the memory screen. With macros - of course. – CashCow Oct 14 '10 at 15:48
  • 2
    Accessing hardware registers via addresses is common practice in embedded systems. They are either defined as constant pointers or declared using `#define`. – Thomas Matthews Oct 14 '10 at 15:57
  • 1
    Why did you go to `void*`? OP's code want a pointer to an `int` – John Dibling Oct 14 '10 at 16:24
  • @John: Good point. Changed it. Thanks. – Coincoin Oct 14 '10 at 17:13
  • 2
    @CashCow: Sure - but you're doing implementation-specific casting no matter what, and `reinterpret_cast` is the C++ way of doing it. It's better because it's easier to find, and flags this as a potentially unsafe operation should anybody try porting this. – David Thornley Oct 14 '10 at 17:15
  • @Coincoin what if the address is already occupied? – Lokanath Nov 21 '16 at 02:34
  • Is there a need, since C++17, to use `std::launder`? like that: `int* ptr = std:: launder(reinterpret_cast(0x12345678));` This relates to @Lokanath comment above: "_what if the address is already occupied?_", or taken a bit differently: _what if another live pointer already points there?_ Then `std::launder` becomes important I believe. – Amir Kirsh Jun 03 '20 at 04:53
2

There is NO standard and portable way to do so. Non-portable ways may include reinterpret_cast(someIntRepresentingTheAddress).

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
1

This will work:

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

address=(void *) 0xdeadbeef; // Some other address
Michael Goldshteyn
  • 71,784
  • 24
  • 131
  • 181
1

In C++, I prefer to declare the pointers as constant pointers in a header file:

volatile uint8_t * const UART_STATUS_REGISTER = (uint8_t *) 0xFFFF4000;

In the C language, this is usually implemented using a macro:

#define UART_STATUS_REGISTER ((volatile uint8_t * const) 0xFFFF4000)

In the rest of the source code, the memory address is referenced via the symbolic name.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
1

I would add that you can call the placement operator for new if you want an objects constructor called when assigning it at the specified address:

int *pLoc = reinterpret_cast<int*>(0x604769);
int *address = new (pLoc) int (1234); // init to a value

This is also used for memory caching objects. Create a buffer and then assign an object to it.

unsigned char *pBuf = new unsigned char[sizeof(CMyObject) + alignment_size];
allign_buf(pBuf);
CMyObject *pMyObj = new (pBuf) CMyObject;
Dan
  • 1,339
  • 3
  • 13
  • 19