13

I'm having trouble with a past exam question on pointers in c which I found from this link, http://www.cl.cam.ac.uk/teaching/exams/pastpapers/y2007p3q4.pdf

The question is this:

A C programmer is working with a little-endian machine with 8 bits in a byte and 4 bytes in a word. The compiler supports unaligned access and uses 1, 2 and 4 bytes to store char, short and int respectively. The programmer writes the following definitions (below right) to access values in main memory (below left):

Address Byte offset
---------0 --1-- 2-- 3
0x04 | 10 00 00 00
0x08 | 61 72 62 33
0x0c | 33 00 00 00
0x10 | 78 0c 00 00
0x14 | 08 00 00 00
0x18 | 01 00 4c 03
0x1c | 18 00 00 00

int **i=(int **)0x04;  
short **pps=(short **)0x1c;  

struct i2c {  
int i;  
char *c;  
}*p=(struct i2c*)0x10;

(a) Write down the values for the following C expressions:

**i  
p->c[2]  
&(*pps)[1]  
++p->i  

I get

**i == 0xc78  
p->c[2] == '62'  
++p->i == 0x1000000  

I don't understand the third question (&(*pps)[1]), could someone please explain what is going on here? I understand the pps pointer has been dereferenced but then the address of operator has been applied to the value. Isn't that just like asking for the adress of a constant, for example if I did this

int i = 7;  
int *p = &i;
&(*p)   //would this mean address of 7??  

Thanks in advance for any help.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 2
    Why the hell do they ask these things instead of teaching useful, clean programming? – salezica Mar 28 '11 at 23:34
  • I'm glad someone else thinks so too. I would also just like to thank everyone for their effort in giving quick concise answers. It is much clearer to me know. –  Mar 29 '11 at 07:30

4 Answers4

7

The [] operator takes precedence over the & operator. So the code is dereferencing pps to get to the first element of an array of short*. Since this element is also a pointer, we may treat it as an array and look up the element one position to the right of what it points to, wth [1]. Finally, we take the address of that element.

It might be useful to note that &p[i] is the same as p + i - it gives you a pointer to the element i positions to the right of where p points to.

The intermediate values are:

pps == 0x1c
*pps == 0x18
&(*pps)[1] == *pps + 1 == 0x1A

(the +1 adds two bytes, since it is used on a short*)

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
  • 3
    Could the person who downvoted me please point out my error(s) so that I can correct it/them? – Aasmund Eldhuset Mar 28 '11 at 23:02
  • +1 for about 20 minutes I thought you were totally wrong (though didn't downvote anyway) but your values seem fine to me – MByD Mar 29 '11 at 07:11
  • +1 Thanks for this, I always forget about the order of precedence and end up trying to evaluate things from left to right. –  Mar 29 '11 at 08:22
  • @ricola86: In that case, let me recommend a thorough reading of the [C++ operator precedence chart](http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence) :-) – Aasmund Eldhuset Mar 29 '11 at 10:01
  • @MByD: To be fair, for about five minutes, the last number was `0x20` instead of `0x1A`, so I _was_ wrong at some point :-) – Aasmund Eldhuset Mar 29 '11 at 10:01
  • @Aasmund Eldhuset: Thanks for that, I'll have a look. –  Mar 29 '11 at 13:22
1

The expression is parsed as &((*pps)[1]); pps is being treated as a pointer to an array, you're accessing the first element of that pointed-to array, and then taking the address of that element.

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

pps is a pointer to pointer to short,

which means that *pps is a pointer to short (or array of shorts),

(*pps)[1] is just like *(*pps + 1) [pointers arithmetic],

and &(*(*pps + 1)) is the address of *(*pps+1),

or, in other words - (*pps+1) (which is a pointer to short).

MByD
  • 135,866
  • 28
  • 264
  • 277
0

pps is a pointer to a pointer. It is dereferencing pps. So now you have a pointer. As arrays are just pointers you are then using pps as an array.

It is then same as:

short ps[2] = {0x0001,0x034c};
short **pps = &ps;

so the result is: 0x034c

PAntoine
  • 679
  • 4
  • 9