2

I have these lines in a C++ program on a RPi 3B:

struct bcm2835_peripheral
{
    unsigned long addr_p;
    int mem_fd;
    void *map;
    volatile unsigned int *addr;
};

struct bcm2835_peripheral gpio = {GPIO_BASE};

cout << "1: " << (gpio.addr) << " = " << *(gpio.addr) << endl;
cout << "2: " << (gpio.addr + 7) << " = " << *(gpio.addr + 7) << endl;

The two cout lines produce the following output:

1: 1 = 0
2: 1 = 1735420271

The thing that puzzles me is the '1' on the LHS of line 2. The second cout line is adding 7 to gpio.addr and so I would expect that the '1' would be '8'. Clearly the *(gpio.addr + 7) is returning a different value, i.e., (gpio.addr + 7) is pointing to a different place in the memory.

I cannot see why the code is returning the '1' rather than an '8'.

7
  • 1
    Neither can I if they are consecutive lines.
    – joan
    Commented Dec 21, 2016 at 15:49
  • 2
    There must be some other problem. gpio.addr is a 32bit pointer to an unsigned int. Therefore it must be aligned to 4 byte boundaries. 1 is definitely not at a 4 byte boundary. But even if the first value would be a valid address then adding 7 would actually add 7*4 = 28 to the address. My best guess is that gpio is invalid.
    – kwasmich
    Commented Dec 21, 2016 at 15:54
  • They are consecutive lines.
    – user34299
    Commented Dec 21, 2016 at 15:56
  • 2
    Actually I'm not sure how you print pointer addresses with std::cout. Try printf("1: %p = %u\n", gpio.addr, *(gpio.addr)); printf("2: %p = %u\n", gpio.addr + 7, *(gpio.addr + 7));
    – kwasmich
    Commented Dec 21, 2016 at 15:57
  • I edited your question, putting code snippets in the right order instead of describing in free text which statement comes after which. Hope that's OK. Commented Dec 21, 2016 at 16:58

1 Answer 1

9

ostream class has no methods to print volatile pointers, and a volatile pointer cannot be converted to a regular pointer without an explicit cast.

However, any pointer can be converted to bool: every pointer value is true except for NULL which is false. This was done to support code which used pointers as conditions, e.g. if(p) use(p[0]);. This implicit conversion is exactly what happens here.

Try the following code and see how your pointers are displayed nicely, using 0xabcd format:

std::cout << "1: " << ((int *)gpio.addr) << " = " << *(gpio.addr) << std::endl;
std::cout << "2: " << ((int *)gpio.addr + 7) << " = " << *(gpio.addr + 7) << std::endl;

Note that the difference between the two pointers will not be 7 but rather 7*sizeof(int), but that's a detail.

1
  • 3
    The "detail" here has to do with how pointer arithmetic works (kwasmich alludes to this in a comment too) -- something fundamental the OP should look up and understand ASAP!
    – goldilocks
    Commented Dec 21, 2016 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.