Трудный указательный вопрос
У меня возникли проблемы с прошлым экзаменационным вопросом по указателям в c, который я нашел по этой ссылке,
http://www.cl.cam.ac.uk/teaching/exams/pastpapers/y2007p3q4.pdf
Возникает вопрос:
Программист C работает с мало-конечная машина с 8 бит в байта и 4 байта в слове. компилятор поддерживает неравномерный доступ и использует 1, 2 и 4 байта для хранения char, short и int соответственно. программист пишет следующее определения (справа внизу) для доступа значения в основной памяти (внизу слева):
Смещение байта адреса
--------- 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) Запишите значения для следующих выражений C:
**i
p->c[2]
&(*pps)[1]
++p->i
Я получаю
**i == 0xc78
p->c[2] == '62'
++p->i == 0x1000000
Я не понимаю третий вопрос (&(*pps)[1]
), может кто-нибудь объяснить, что здесь происходит? Я понимаю, что указатель pps был разыменован, но затем адрес оператора был применен к значению. Разве это не так, как просить адрес константы, например, если бы я сделал это
int i = 7;
int *p = &i;
&(*p) //would this mean address of 7??
Заранее благодарим за любую помощь.
Ответы
Ответ 1
Оператор []
имеет приоритет над оператором &
. Таким образом, код разыменовывает pps
, чтобы перейти к первому элементу массива short*
. Поскольку этот элемент также является указателем, мы можем рассматривать его как массив и искать элемент, расположенный справа от того, на что он указывает, wth [1]
. Наконец, мы берем адрес этого элемента.
Может быть полезно отметить, что &p[i]
совпадает с p + i
- он дает вам указатель на позиции элемента i
справа от того, где p
указывает на.
Промежуточные значения:
pps == 0x1c
*pps == 0x18
&(*pps)[1] == *pps + 1 == 0x1A
(+1
добавляет два байта, поскольку используется на short*
)
Ответ 2
Выражение анализируется как &((*pps)[1])
; pps
обрабатывается как указатель на массив, вы получаете доступ к первому элементу этого массива с указателем, а затем берете адрес этого элемента.
Ответ 3
pps
является указателем на указатель на короткий,
что означает, что *pps
является указателем на короткий (или массив шорт),
(*pps)[1]
похож на *(*pps + 1)
[арифметика указателей],
и &(*(*pps + 1))
- адрес *(*pps+1)
,
или, другими словами, (*pps+1)
(который является указателем на короткий).
Ответ 4
pps - указатель на указатель.
Это разыменование pps. Итак, теперь у вас есть указатель. Поскольку массивы - это просто указатели, вы используете pps в качестве массива.
Это то же самое, что и:
short ps[2] = {0x0001,0x034c};
short **pps = &ps;
поэтому результат: 0x034c