2013-06-16 4 views
1

Я проводил пару дней, пытаясь понять указатели, но синтаксис все еще меня смущает.Путаница синтаксиса указателя (* ptr vs ptr)

Когда вы пишете, скажите, int *ptr;, в чем разница между ptr и *ptr после этой декларации?

В K & R они начинают главу указателей на этом примере:

int x = 1, y = 2, z[10]; 
int *ip; /* ip is a pointer to int */ 
ip = &x; /* ip now points to x */ 
y = *ip; /* y is now 1 */ 
*ip = 0; /* x is now 0 */ 
ip = &z[0]; /* ip now points to z[0] */ 

Это заставило меня думать, что *ip использовали для целочисленных значений (так как *ip была объявлена ​​Int) в то время как обычная ip использовался для адресов , и ip (&x) будет «указывать на» *ip (x). Другими словами, адрес x будет указывать на x.

Но тогда приходит пример, который бросает эту идею под автобус.

swap(&a,&b); 

void swap(int *px, int *py) /* interchange *px and *py */ 
{ 
    int temp; 
    temp = *px; 
    *px = *py; 
    *py = temp; 
} 

На основании задания функции, это ясно *px = &a и *py = &b, который эффективно побеждает мою идею, что только px и py может хранить адреса, не *px и *py. Это меня очень смущает связь между px & *px и py & *py.

Я сделал некоторые эксперименты после этого:

int x = 4; 
int y = &x; 
printf("%d %p \n",y,&y); 

... и заметил это на самом деле компилирует правильно, хотя значения y и &y незначительно отличаются при преобразовании из шестнадцатеричной в десятичную и наоборот.

Это оставляет меня более смущенным, чем когда-либо, и очевидно, что существует некоторая фундаментальная концепция о указателях, которые я просто не понимаю, независимо от того, сколько времени и энергии я посвящаю ей.

ответ

6

Это заставило меня думать, что *ip использовали для целочисленных значений (так как *ip был объявлен int) в то время как обычная ip использовался для адресов, и ip (&x) будет «точка» *ip (x). Другими словами, адрес x будет указывать на x.

Это верно. В точку.

(ну, почти. Это не значит, что *ip был объявлен int, но ip был объявлен int *. Вот что смущает вас, смотрите следующую часть.)

На основании задания функции, то ясно *px = &a и *py = &b

Нет, не существует.

px и py - сами указатели. px = &a и py = &b, и изначально *px = a и *py = b (конечно, после обмена, это изменяется).

Что, по-видимому, смущает вас во втором случае, так как символ * имеет два значения в контексте указателей.

Тот есть, когда вы объявить переменная типа указатель, то * символ действует как указатель классификатором, я. е. T *p указывает, что переменная p является указателем на тип T.

Другой смысл является *оператор, который не используется в объявлениях, но в выражениях, где он разыменовывает указатель, я. е. он обращается к значению, на которое он указывает.

+0

+1 для объяснения двух значений – pinkpanther

+2

@ Amalgam54 Потому что это не намного интуитивно. На самом деле это вводит в заблуждение. 'int * p1, p2;' визуально предполагает, что 'p1' и' p2' имеют тип 'int *', тогда как определитель указателя применяется к ** переменным **, а не ** типам **, поэтому только 'p1' это 'int *', а 'p2' - простой' int'. Вот почему 'int * p1, p2;' (а иногда и 'int * p1, * p2;') концептуально более корректен. –

+0

Пришлось прочитать ваше объяснение несколько раз, но теперь это имеет смысл. Спасибо за всю помощь, это очень ценится! – ericgrosse