С передачей указателя на функцию путаницы - PullRequest
0 голосов
/ 04 июля 2011

Я немного запутался здесь.Это из большой книги по Си, и, может быть, я слишком много сомневаюсь в этом, но почему-то это не имело смысла.Я надеюсь, что смогу объяснить свою путаницу.

Допустим, ниже &a указывает на адрес памяти 87, а &b указывает на адрес памяти 120;

int a = 3;
int b = 4;
swap(&a, &b);

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

ОК, здесьвопрос: когда мы вызываем функцию swap и передаем параметры функции , устанавливаем ли мы «px» на 87 или «* px» на 87?

Потому что если мыустанавливаем * px на 87, а затем по определению знака * мы устанавливаем значение, на которое ссылается указатель, но не адрес памяти p, что неверно в этом примере.С другой стороны, если мы на самом деле устанавливаем «p» равным 87, тогда код в swap имеет смысл, потому что тогда, когда мы будем использовать знак * в функции, мы будем ссылаться на значение в этом адресе, которое равно «3».Вот.Но тогда почему синтаксис сбивает с толку и выглядит так, как будто мы устанавливаем

*px = 87

?

Ответы [ 7 ]

4 голосов
/ 04 июля 2011

Если a по адресу 88 (необходимо правильно выровнять) и b по адресу 120, то:

                                //   a   |   b   |   px   |  py   | temp
int a=3;                        //   3       --      --       --     --
int b=4;                        //   3       4       --       --     --
swap(&a, &b);                   //   4       3       --       --     --

void swap(int *px, int *py)
{                               //   3       4       88      120    --
  int temp;
  temp = *px;                   //   3       4       88      120     3
  *px = *py;                    //   4       4       88      120     3
  *py = temp;                   //   4       3       88      120     3
}

px равно &a, что 88никогда не меняется.*px обозначает (псевдонимы) a.Он может быть привязан к псевдониму другой переменной, но этот код этого не делает.

Параметр px и имеет тип int*.Параметр не *px.По этой причине многие программисты пишут это как int* px вместо int *px.Эффект вызова swap(&a, &b) заключается в том, что px = &a, а не *px = &a.

Но, пожалуйста, обратите внимание, что C не имеет "методов", только "функции".

2 голосов
/ 04 июля 2011

* может означать три разные вещи, в зависимости от контекста:

  • В a * b это означает умножение.
  • В int *a, это означает, что «мы теперь объявляем переменную или параметр a, тип которых равен int * (указатель на int).
  • In *a (при условии, что нет типа данных дляслева от *, так что это выражение , а не объявление ), это означает, что "a является указателем, и мы хотим посмотреть на его значениеуказывает на (также известный как разыменование указатель ".

Таким образом, параметр вашего метода равен a, а не *a; звездочка является частью типа параметраи a - это то, что вы устанавливаете на 87. Запись объявлений указателей как int * a или int* a вместо int *a может помочь сделать различие между объявлением и разыменованием более четким.

2 голосов
/ 04 июля 2011

Рассмотрим вашу подпись swap:

void swap(int *px, int *py);

Это означает, что своп берет два указателя на int. Другой способ выразить это: он занимает два адреса int значений в памяти.

Теперь при вызове вашей swap функции, такой как

swap(&a, &b);

первый аргумент будет адресом a (который является int), а второй аргумент будет адресом b (который также является int).

Внутри swap, px будет адресом a, а py будет адресом b. Следовательно, разыменование px и py приведет к значениям по адресам a и b - которые будут 3 и 4.

1 голос
/ 04 июля 2011

Переменная a указывает на адрес памяти 87. &a равен 87. И затем мы устанавливаем px в 87. Конечно, это адреса, а не целые числа, но это очень близкок тому, что происходит в ЦП (конечно, в ЦП нет a, &a или px).

1 голос
/ 04 июля 2011

Вы не устанавливаете никаких указателей, вы всегда устанавливаете только значение для pointee .*px = *py установит a в значение b.

1 голос
/ 04 июля 2011
void swap(int *px, int *py) 

Вы читаете это, что px и py указывают на int. Параметры в C передаются по значению. Поэтому, когда вы передаете два адреса памяти (то есть указатели) на swap, вы назначаете эти адреса px и py.

Возможно, путаница связана с сильной перегрузкой * в C. В списке параметров * означает, что параметр является указателем на тип слева. В реализации функции * используется для разыменования указателя.

0 голосов
/ 04 июля 2011

На самом деле мы устанавливаем «px» на 87 или «* px» на 87?

Да, вы устанавливаете px на 87.Вы заставляете указатели указывать на одно и то же местоположение при изменении значений, на которые они указывают.

"Потому что, если мы устанавливаем * px на 87" ...

Нет, вы предполагаете, чтонеправильно.

...