Попытка понять функцию, чтобы поменять местами два значения int - PullRequest
0 голосов
/ 07 сентября 2018

Я знаю, что эта функция меняет два значения типа int, но я пытаюсь в мельчайших подробностях понять, что именно делает * x = * y .

 1 void swap (int* x, int* y){
 2    int temp = *x; 
 3    *x = *y;
 4    *y = temp;
 5 }
 6
 7 int x,y;
 8 x = 1;
 9 y = 2;
10 swap(&x,&y)

Функция получает дваадреса, где соответственно живут x и y .

Создается переменная типа int temp , которой присваивается значение 1 из разыменованного указателя в x.

Значение 1 из разыменованного указателя в x присваивается значение 2 изразыменованный указатель на y .Итак, к * x = * y я читаю 1 = 2

Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Когда вы назначаете что-то вроде int abc = 5; int *ptr = &abc;, понимаете, что:

  • ptr - целочисленный указатель
  • &abc - адрес переменной abc
  • ptr хранит адреса переменной abc
  • Запись *ptr является эквивалентом записи abc и не совпадает с записью 5 (константа), хотя все три значения в выражении 5.

Оператор * разыменовывается, чтобы дать вам переменную, на адрес которой указывает ptr (т.е. abc). Поэтому его можно использовать как lvalue (слева от назначения).

Теперь в вашем примере, когда вы пытались присвоить x = *y, вы пытаетесь сохранить значение, на которое указывает y (что является целочисленным значением), до x (которое ожидает адрес).

Теперь предположим, что вы как-то сделали назначение, давайте также предположим, что &y (то есть адрес y) - это что-то вроде 1056 (только для примера), а значение, на которое указывает y, - что-то вроде 5. Затем с этого момента x указывает на местоположение адреса 5 (которое не является фактическим адресом), что приводит к некоторому значению мусора.

Теперь назначение типа x = y будет работать безупречно. Но это заставит указатели x указывать на то же место, на которое указывает y, поменять местами их наведение. Это если изначально, если x указывал на переменную a, которая находилась по адресу 1000, а y указывал на переменную b, которая находилась по адресу 2000, после значения присвоения обоих x и y будет 1000. Это означает только то, что теперь у нас есть два указателя на переменную b по адресу 2000, но это не влияет на реальные переменные. Принимая во внимание, что запись *x = *y эквивалентна записи a = b

Надеюсь, это помогло.

0 голосов
/ 07 сентября 2018
  1. Здесь, в swap(&x, &y);, вы передаете адреса переменной x & y в качестве аргументов функции swap(int* x, int* y).
  2. Поскольку параметры функции swap являются указателями типа int, адреса x и y теперь сохраняются в переменных другого типа указателя типа int x и y.

    НОТА:

    x и y имеют одинаковое имя в обеих функциях, но x и y, используемые в функции подкачки, являются указателями int, а x и y, используемые вне функции подкачки, int переменных.

  3. Значению 1 от разыменованного указателя на x присваивается значение 2 от разыменованного указателя на y. Итак, * x = * y, я читаю 1 = 2

    *x=*y фактически использует оператор присваивания с ассоциативностью слева направо. Оператор присваивания присваивает значение правого операнда левому операнду. не считайте его как 1 = 2, это будет, поскольку это может оказаться проблематичным позже.

  4. Я пытался сделать некоторые предположения. По * x = * y, я думаю * x не разыменовывает x, но является адресом x, и ему присваивается значение 2 разыменованного указателя для y.

    *x=*y здесь, *x - это значение x, а не адрес x, и, как описано в пункте 3, этот оператор будет присваивать значение *y, то есть от 2 до *x.

  5. Но почему вместо * x = * y не должно быть просто x = * y?

    не должно быть, потому что x - это указатель int, а *y - это int переменная.

0 голосов
/ 07 сентября 2018

Давайте попробуем объяснить *x = *y;, не используя слово «разыменование»:

  • *x представляет целочисленный объект, на который указывает x. Поскольку это левый операнд присваивания, это означает, что этот целочисленный объект будет обновлен.
  • *y представляет целочисленный объект, на который указывает y. Поскольку это правильный операнд присваивания, это означает, что будет использоваться содержимое целочисленного объекта (то есть его значение).
  • *x=*y обновляет целочисленный объект, на который указывает x, на целочисленный объект, на который указывает y.

Примечание: Чтобы четко отличать указатели от других типов в коде, я предлагаю вам изменить именование следующим образом, используя префикс типа p_ для переменных указателя, например:

 1 void swap (int* p_x, int* p_y){
 2    int temp = *p_x; 
 3    *p_x = *p_y;
 4    *p_y = temp;
 5 }
 6
 7 int x,y;
 8 x = 1;
 9 y = 2;
10 swap(&x,&y)
...