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'.

  • 1
    Neither can I if they are consecutive lines. – joan Dec 21 '16 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 Dec 21 '16 at 15:54
  • They are consecutive lines. – user34299 Dec 21 '16 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 Dec 21 '16 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. – Dmitry Grigoryev Dec 21 '16 at 16:58
8

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.

|improve this answer|||||
  • 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 Dec 21 '16 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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