-2

Can someone explain me the difference between the following defines:

#define ADDR_VAL(x) (*((volatile unsigned long *)(x)))

and

#define ADDR_VAL(x) (*((volatile unsigned long *)x))

In my case mostly the usage will be like:

#define INTR_SRC(x) ADDR_VAL(INTR_BASE_VAL(x) + 0x180)

INTR_SRC(0) = 0x24ul;

Assuming that INTR_BASE_VAL(x) is a value calculated to 0x1A002D00, do both of the above menioned ADDR_VAL(x) defines provide the same results for the INTR_SRC define?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Quest
  • 129
  • 1
  • 1
  • 8

2 Answers2

3

The first one will cast all x expression to volatile unsigned long * while the second one - only its first part.

For example, in first case, the whole INTR_BASE_VAL(x) + 0x180 will be converted to volatile unsigned long * while in the second one - just INTR_BASE_VAL(x).


First expression unrolled:

(*((volatile unsigned long *)(INTR_BASE_VAL(x) + 0x180)))

The whole expression gets casted and then dereferenced

Second expression unrolled:

(*((volatile unsigned long *)INTR_BASE_VAL(x) + 0x180))

Only the first part gets casted but the whole thing (INTR_BASE_VAL(x) casted to a pointer plus the value of 0x180) is dereferenced.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • So am I correct in saying in the second one the resultant value will be a dereferenced value of INTR_BASE_VAL(x) + 0x180*(sizeof(unsigned long)) while in the first one its equivalent to a dereferenced value of (INTR_BASE_VAL(x) + 0x180) – Quest Oct 31 '15 at 15:11
  • @Quest, please check my edits. I'm not quite sure where `sizeof(unsigned long)` comes from in your comment. – ForceBru Oct 31 '15 at 15:21
0

Given the usage

ADDR_VAL(INTR_BASE_VAL(x) + 0x180)

The first form will expand to

(*((volatile unsigned long *)(INTR_BASE_VAL(x) + 0x180)))

The expression INTR_BASE_VAL(x) + 0x180 is cast to type volatile unsigned long * and then dereferenced.

The second form expands to

(*((volatile unsigned long *) INTR_BASE_VAL(x) + 0x180))

The expression INTR_BASE_VAL(x) is cast to type volatile unsigned long *, 0x180 is added to the result, and the result of the addition is dereferenced.

Does it make a difference? Depends on what the type of INTR_BASE_VAL(x) winds up being. Remember that pointer arithmetic is based on the type of the pointed-to object: p + 1 will give a different address if p is a char * vs an int *. So if INTR_BASE_VAL(x) evaluates to a type that's a different size than unsigned long, the two forms will give different results.

In this case, you should use the first form.

John Bode
  • 119,563
  • 19
  • 122
  • 198