0

I've been using some example code that runs in an ARM processor. To read a specific memory location it casts a constant value to an address.

For example:

We want to read a memory value at 0xa0000000

The example code is like this:

uint32_t test_data;

const uint32_t test_address = 0xa0000000;

test_data = *(uint32_t*) test_address;

I don't quite understand the cast *(uint32_t*). It seems to me that just one * is enough.

I'd appreciate a bit of explanation.

Thanks.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • 1
    `(uint32t *)` casts the address to a pointer. But you don't want to read the pointer value itself (because you have already got it, it's the constant) – you want to read the memory that is pointed to by that pointer, which you achieve by **dereferencing** the pointer using the `*` operator. – The Paramagnetic Croissant Jan 09 '15 at 21:24
  • `*op` makes no sense (compiler error) if x is an integer type. It makes sense if `op` is a pointer: it is the dereference oeprator and it dereferences the pointer `op`. Since `test_data` is an integer type, a cast to a pointer is needed. – bolov Jan 09 '15 at 21:24

3 Answers3

2

You're storing a pointer as a uint32_t instead of a pointer to uint32_t. That's why you have to do the additional cast.

I'd recommend the following:

#include <iostream>

int main(int argc, const char** argv) {
    volatile uint32_t* const test_address = reinterpret_cast<uint32_t*>(0xa0000000);
    uint32_t value = *test_address;
    return 0;
}
Jason
  • 1,086
  • 5
  • 10
  • 1
    Would it make sense to make `test_address` a pointer to `volatile` as well? Might need that if it's actually a memory-mapped I/O address or something. – Fred Larson Jan 09 '15 at 21:32
  • Yeah, probably. I don't have a CPU to test it on, but I think you're right. Thanks, Fred. – Jason Jan 09 '15 at 21:35
1

The cast (uint32_t*) test_address reinterprets the value of test_address as an address, and yields a pointer pointing to that address. This C-cast has the same effect a reinterpret_cast would have - and really, reinterpret_cast should be used instead.

To get the value that pointer is pointing too, i.e. its pointee, it is necessary to dereference it via *. That gives us * ((uint32_t*) test_address), or equivalently *(uint32_t*) test_address.

Columbo
  • 60,038
  • 8
  • 155
  • 203
0

its clearer if you split

test_data = *(uint32_t*) test_address;

into two steps

uint32_t  *p = (uint32_t*) test_address;
test_data = *p;

The first is the cast, the second is the dereference

pm100
  • 48,078
  • 23
  • 82
  • 145