Почему этот код указателя C не работает? - PullRequest
3 голосов
/ 13 октября 2011

Пройдите C newb здесь. Попытка выучить / понять указатели, возиться с простыми фрагментами кода.

#include <stdio.h>

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

main()
{
    int *a, *b;
    *a = 1;
    *b = 2;
    swap(&a,&b);
    printf("%d %d\n", *a, *b);
}

Почему это недействительно? Код работает, когда я удаляю оператор разыменования * из main.

Концептуально это должно работать. Я инициализирую a и b как указатели, которые указывают на int 1 и int 2 соответственно. Затем я отправляю их адреса на swap(), что должно изменить то, на что они указывают.

Ответы [ 6 ]

11 голосов
/ 13 октября 2011

Есть пара проблем.Во-первых, указатели a и b не указывают на допустимую память.Таким образом, назначение целочисленных значений не определено (возможный сбой).Во-вторых, вызов swap (при условии, что a и b указывают на действительную память) не должен включать адрес (в данный момент он отправляет адрес переменной указателя).

Следующие изменения позволят ему работать:1005 *

int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
6 голосов
/ 13 октября 2011

Функция swap() в порядке, но внутри main вы берете адреса указателей , поэтому вы передаете int** аргументы int* параметрам.

int *a, *b;
swap(&a,&b);

Чтобы исправить это, замените код в main() на:

int a = 1, b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
4 голосов
/ 13 октября 2011

Указатели указывают на данные.Сам указатель не содержит памяти для хранения, он просто указывает на существующую память.Поэтому, когда вы объявляете int *a;, у вас просто есть указатель мусора без полезного значения, и вы не должны разыменовывать его.

Единственный разумный способ использовать указатели - назначить им адрес чего-либоили результат некоторой функции выделения):

int i;
int *a = &i;  // now a points to i

Следовательно, правильный способ использовать вашу функцию подкачки - передать ей целые адреса:

int i = 10;
int j = -2;

swap(&i, &j);
2 голосов
/ 13 октября 2011

a и b являются неинициализированными указателями, разыменование которых вызывает неопределенное поведение. Вы хотите:

int main() {
    int a, b;
    a = 1;
    b = 2;
    swap(&a,&b);
    printf("%d %d\n", a, b);
    return 0;
}
0 голосов
/ 13 октября 2011

Когда вы говорите: «Затем я отправляю их адреса в swap (), который должен переключать то, на что они указывают».Вы пытаетесь изменить значения адреса в переменных указателя в main, чтобы переключиться на какой бит памяти они указывают?В этом случае вам потребуется еще один шаг перенаправления:

#include <stdio.h>

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

int main (void) {
  int x, y; /* storage to point to */
  int *a, *b;

  a = &x;
  b = &y;

  *a = 1;
  *b = 2;

  printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
  swap(&a, &b);
  printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
}

$ ./a.out
(*a, *b, x, y) == (1, 2, 1, 2)
(*a, *b, x, y) == (2, 1, 1, 2)

Значения x & y не изменились, но a указывал на x и теперь указывает на yи наоборот для b.

0 голосов
/ 13 октября 2011

Ваш метод подписи неверен.Вы запрашиваете два указателя на int, но передаете два указателя на указатели на int.

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