Изменить переданный указатель в функции - PullRequest
1 голос
/ 28 апреля 2020

Относительно двойной косвенности (указатель на указатель) и передачи их в функцию

Я не могу изменить указатель здесь в функции void test (int ** nmbr, int * n);

int n = 5;
int n2 = 555;   

int *nPtr = &n;
int *n2Ptr = &n2;

printf("the number = %d\n", *nPtr);

test(&nPtr, n2Ptr);

printf("the number is now = %d\n", *nPtr);

test

void test(int **nPptr, int *n2Ptr) {

 int *p = *nPptr;

 p = n2Ptr;

}

, поскольку указатель p указывает на копию * nPtr, верно?

Но как насчет этого кода (на этот раз указатель указывает для данной структуры в связанном списке

фрагмент кода взят с сайта https://www.learn-c.org/en/Linked_lists

 int remove_by_index(Person **head, int n) {
int i = 0;
int retval = -1;
Person *current = *head;
Person *temp_node = NULL;

if (n == 0) {
    return pop_first(head);
}

for (i = 0; i < n-1; i++) {
    if (current->next == NULL) {
        return -1;
    }
    current = current->next;
}

temp_node = current->next;
retval = temp_node->nmbr;
current->next = temp_node->next;
free(temp_node);

return retval;

}

удаляет указанный узел в списке по указанному номеру индекса

Здесь можно увидеть, что * current является локальной копией в функции и перемещается по списку и, наконец, объединяет два узла без проблем

Так почему же работает изменение указателя здесь, но не в тесте функции (int ** nPptr, int * n2Ptr)?

Чтобы быть понятным

в функции test :

 int *p = *nPptr;

p является локальной копией и копирует указатель из * nPtr

в функцию remove_by_index

Person *current = *head;
* 10 40 * current является локальной копией и копирует указатель с * head. Список выходит за рамки функции remove_by_index (..), поэтому я не понимаю, почему им можно манипулировать в функции с помощью локального указателя * current, в то же время он не работает для изменения nPtr в тесте функции ( ..)

1 Ответ

1 голос
/ 28 апреля 2020

В функции изменения переменных-указателей или параметров-указателей не действуют вне функции. Однако, если указатель указывает на объект вне функции, этот объект можно изменить, разыменовав указатель.

Например, в функции OP test:

void test(int **nPptr, int *n2Ptr) {
    int *p = *nPptr;

    p = n2Ptr;
}

p инициализируется, а затем его значение изменяется присваиванием. Это не влияет ни на один объект за пределами функции. Если функция была изменена следующим образом:

void test(int **nPptr, int *n2Ptr) {
    int *p = *nPptr;

    p = n2Ptr;

    *nPptr = p;
    *p = 42;
}

, тогда два объекта вне функции будут изменены (int * и int).

В операциях remove_by_index функция, изменения переменной current по мере ее продвижения по связанному списку не имеют внешнего эффекта, но строка:

current->next = temp_node->next;

эквивалентна:

(*current).next = (*temp_node).next;

Внешний Person объект, на который current указывает в связанном списке, был изменен путем разыменования указателя и присвоения элементу next Person, на который он указывает.

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