массив указателей - PullRequest
       1

массив указателей

0 голосов
/ 12 апреля 2011

Рассмотрим следующий код:

#include <stdio.h>

int main()
{
  static int a[]={0,1,2,3,4};
  int *p[]={a,a+1,a+2,a+3};            /* clear up to this extent */
  printf(("%u\n%u\n%u",p,*p,*(*p)));   /* how does this statement work? */
  return 0;
}

Также необходимо получить значение адресов через %u, или мы также можем использовать %d?

Ответы [ 5 ]

1 голос
/ 27 мая 2011

С этими дополнительными скобками запятые становятся операторами запятых, поэтому в printf передается только последний ** p. Поскольку printf ожидает, что его первый аргумент будет указателем на строку символов, и в большинстве систем указатели и целые числа имеют одинаковый размер, поэтому целое число 0 интерпретируется как указатель NULL, а printf вообще ничего не печатает. Или это вылетает. Это проблема с неопределенным поведением.

1 голос
/ 12 апреля 2011

У вас есть лишняя пара слов в выражении printf?

В любом случае, вы можете думать об этом утверждении:

printf("%u\n%u\n%u",p,*p,*(*p));

как следование за указателями.

  • p - это сам указатель, при печати он должен распечатать значение указателя, которое является адресом того, на что он указывает. В вашем случае это массив (int *).
  • * p - это операция разыменования . Это позволяет получить доступ к объекту, на который указывает p. В других ответах вы видите заметки о том, что * p эквивалентно p [0]. Это потому, что p указывает на начало вашей структуры, которая является началом массива.
  • ** p - это операция разыменования объекта указателя, на который указывает p. Расширяя пример из предыдущего пункта, вы можете сказать, что ** p эквивалентно * (p [0]), что эквивалентно * (a), что эквивалентно a [0].

Один совет, который может помочь вам при попытке расшифровать такого рода операторы, - помнить о правилах старшинства языка C и вставлять в выражения операторы между выражениями в выражении, чтобы разбить оператор. Для ** p вставка паренина будет делать это: * (* p), что проясняет, что вы должны следовать двум указателям до конечного пункта назначения.

1 голос
/ 12 апреля 2011

Хорошо, вы создали массив целых чисел и заполнили его целыми числами от 0 до 4. Затем вы создали 4-элементный массив указателей на целые числа и инициализировали его так, что его четыре элемента указывают на первые четыре элементаа.Пока все хорошо.

Тогда printf очень странный.printf передается один аргумент, а именно ("% u \ n% u \ n% u", p, p, (* p)).Это выражение запятой, которое означает, что выражения, разделенные запятыми, будут вычислены по очереди, и будет возвращено только последнее.Так как самое первое - это литерал, а не выражение, я ожидаю, что оно вызовет ошибку.Однако без лишних скобок у вас есть:

printf("%u\n%u\n%u\n",p, *p, *(*p));

Это законно.В printf передаются три значения, которые интерпретируются как целые числа без знака (которые на самом деле работают только в некоторых системах, поскольку в действительности вы передаете указатели в первых двух случаях, и они не гарантируют, что они имеют тот же размер, что и целые числа без знака)и напечатано.

Это значения p, * p и ** p.p является массивом, и поэтому значение p является адресом массива.* p - это то, на что указывает p, которые являются значениями массива.* p - первое значение, * (p + 1) - второе значение и т. д. Теперь * p - это значение, сохраненное в p [0], который является адресом [0], поэтому печатается другой адрес.Третий аргумент - это ** p, который является значением, хранящимся в (* p), или a [0], который равен 0

0 голосов
/ 12 апреля 2011

Моя память на C-указателях немного ржавая, но позвольте мне посмотреть, могу ли я вспомнить.

p должно быть местом в памяти, оно указывает ни на что иное, кроме p.

* p разыменовывает (переходит в ячейку памяти и возвращает там значение) p. поскольку сам p является указателем на указатели (* p [] также можно записать как ** p), когда мы разыменовываем p, мы получаем первое значение в определении массива или адрес a.

** p разыменования * p. * р - это адрес а. Если мы разыменовываем это, мы получим значение, которое мы поместили в первое место, а это 0

0 голосов
/ 12 апреля 2011

Ваши printf() аргументы работают так:

  • p - это адрес (это массив указателей)
  • *p также является адресом (он эквивалентен p[0], который равен a)
  • *(*p) - это целое число (это a[0])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...