1

This Line defines address for DDRD register in avr microcontroller

#define myDDRD *((volatile unsigned char* const) 0x31)

Can you please clarify how pointers is used in the above line? Why do we need the first asterisk? shouldn't the second one be enough to point to the address 0x31?

Ajay Brahmakshatriya
  • 8,993
  • 3
  • 26
  • 49
user247954
  • 79
  • 1
  • 8
  • it is a `const` pointer to a `volatile unsigned char` . If you just need help with reading it. – Ajay Brahmakshatriya Jul 26 '17 at 09:21
  • The asterisk `*` can mean different things in different scopes. It can mean multiplication if used as a binary operator. It can mean pointer is used in a type (like the typecast `(volatile unsigned char* const)`). Or it can mean *dereference a pointer* if used as an unary operator (which is what's happening here with the "first" asterisk). – Some programmer dude Jul 26 '17 at 09:22
  • @user247954 it's an external resource. But someone already did the work for you. –  Jul 26 '17 at 09:22
  • @AjayBrahmakshatriya I get that but shouldn't the second asterisk be enough to define this pointer? why do we need 2 asterisks? – user247954 Jul 26 '17 at 09:23
  • It's not defining the macro as an address. That macro is replaced in code by an lvalue. – StoryTeller - Unslander Monica Jul 26 '17 at 09:23
  • @user247954 the outer most * is just to dereference this address. Basically it reads a single `BYTE` from the address `0x31`, everywhere this macro is used. – Ajay Brahmakshatriya Jul 26 '17 at 09:24

1 Answers1

8

You can separate *((volatile unsigned char* const) 0x31) into 2 parts:
one inner part: (volatile unsigned char* const) 0x31
and one outer part: *( inner part ).

The inner part casts the integer 0x31 to a volatile unsigned char pointer which is constant.
A pointer type consist of the type name and an asterisk after the type name: type*. To cast an expression parenthesis are uses (type)expression.

The outer part dereferences the address the pointer contains as the asterisk is in front of it: *pointer in order to access it's value.

If we take the inner part only why it isn't enough to read and write from the address?

Imagine a pointer int* intPtr pointing to a valid integer already. If you now want to change that integer you have to do it by *intPtr = 42;. If you would do instead intPtr = 42; you would write 42 to the pointers value and not to the address it points to, so that 42 would be the new address the pointer contains.

In short:
The macro reads one byte (unsigned char) from address 0x31 if it's on the right hand side of an assigment and writes one byte to it if it's on the left hand side.

Usage:
A typical usage is to do bit manipulation like clearing or setting single bits on that register lying on that specific address:

myDDRD &= ~(1 << PD0); /* clear bit 0 as PD0 is defined as 0 */
myDDRD |= (1 << PD1);  /* set bit 1 as PD1 is defined as 1   */

For more information about bit manipulation, see here: How do you set, clear, and toggle a single bit?

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
  • 1
    It can be used to *write* to the address as well, if used as the lhs of an assignment. – Some programmer dude Jul 26 '17 at 09:31
  • If we take the inner part only why it isn't enough to read and write from the address? – user247954 Jul 26 '17 at 09:37
  • @user247954: Because it's just the pointer poiting to an address. To get access to that specific address you have to dereference it. If you have for example a `int* intPtr` and would use it by `intPtr = 42` you would write 42 to the pointers value and not to the address which the pointer contains. – Andre Kampling Jul 26 '17 at 09:41
  • @AndreKampling Ok I got it. Thank you for the clear explanation. – user247954 Jul 26 '17 at 09:44