Указатель с двойным указателем - PullRequest
0 голосов
/ 09 сентября 2018

Почему я не могу назначить указатель на указатель с двойным указателем? Я каждый раз получаю ошибку сегментации.

#include <stdio.h>

int main() {
    int **pointer1, *pointer2, *pointer3, var;

    var = 10;
    pointer3 = &var; 
    pointer1 = &pointer3;
    pointer2 = *pointer1;   //correcting my mistake, so this is now correct?

    return 0;
}

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

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t {
    int num;
    struct node_t *next;
} node_t;

void insert(int, node_t**);

int main(void) {
    int list;
    node_t **head, *temp;

    *head = NULL;

    while (scanf("%d", &list) != EOF) {
        insert(list, head);
    }
    temp = *head;
    /*while (temp != NULL) {      //here is the problem, if I remove this 
                                  //I get segmentation fault but it runs 
        printf("%d ", temp->num); //runs fine when I include it
        temp = temp->next;

    }*/
    return 0;
}

void insert(int list, node_t **head) {
    node_t *temp = malloc(sizeof(node_t));
    temp->next = (*head);
    temp->num = list;
    (*head) = temp;
}

Точно так же, как то, что я вставил в комментарий к коду, вышеприведенная версия моего кода получает ошибку сегментации, когда я компилирую ее без цикла while. Но как ни странно, он работает нормально, если я включаю цикл while. После возни, я подозреваю, что виновником является двойной указатель, в котором я пытался назначить дополнительный адрес в обычный указатель. Но эта версия на самом деле работает нормально:

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t {
    int num;
    struct node_t *next;
} node_t;

void insert(int, node_t**);

int main(void) {
    int list;
    node_t *head, *temp;

    head = NULL;

    while (scanf("%d", &list) != EOF) {
        insert(list, &head);
    }
    temp = head;
    while (temp != NULL) {

        printf("%d ", temp->num);
        temp = temp->next;

    }
    return 0;
}

void insert(int list, node_t **head) {
    node_t *temp = malloc(sizeof(node_t));
    temp->next = (*head);
    temp->num = list;
    (*head) = temp;
}

Здесь я передал адрес в функцию связанного списка, и, по сути, я делаю то же самое, но без двойного указателя.

Кстати, я видел много разных реализаций связанных списков. Мой требует двойной указатель, потому что я использую void insert(int, **node_t), но есть версии, которые возвращают адрес и обновляют заголовок: node_t* insert(int, *node_t) и Глобальный связанный список: void insert(int). Просто интересно, какие версии на самом деле рекомендуются, проще в отладке и удобны для начинающих.

Ответы [ 2 ]

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

Когда вы делаете это:

 **pointer1 = 10;

То, что это говорит: «возьмите адрес, сохраненный в pointer1, разыменуйте этот адрес, возьмите адрес, сохраненный там , снова разыщите и сохраните значение 10 в этом месте».

Это выглядит примерно так:

pointer1
-------     -------    ------
|  .--|---->|  .--|--->| 10 |
-------     -------    ------

Вы получаете segfault, потому что pointer1 в настоящее время нигде не указывает.

Это может сработать, если вы сделаете что-то вроде этого:

int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;

В случае двух «настоящих» фрагментов кода проблема с первым фрагментом кода заключается в том, что вы передаете head неинициализированным в insert, который затем разыменовывается head. Это та же проблема, что и выше. То же самое происходит снова в main, потому что head все еще неинициализирован после вызова list, потому что он был передан по значению. Второй фрагмент кода работает, потому что вы передаете адрес head на insert, поэтому впоследствии разыменовываете его действительный.

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

Ваш первый пример segfaults, потому что *pointer1pointer1 перед ним) ни на что не указывает.Это неинициализированный указатель, который указывает на случайные данные мусора в памяти.

Попытка разыменования такого указателя (**pointer1 = 10;) приводит к segfault.

Решением для работы вашего первого примера будет выделение некоторой памяти для данных, которые вы пытаетесь сохранить:

int **pointer1, *pointer2;

int *data = malloc(sizeof(int));

pointer1 = &data;
**pointer1 = 10;

pointer2 = *pointer1;

free(*pointer1); //or free(data)
...