C: Инициализация структуры и назначение ее указателю в параметре функции - PullRequest
0 голосов
/ 26 октября 2019

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

Поскольку я ужасно объясняю вещи, я получил небольшой примерс фактическим и ожидаемым результатом:

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

struct foo {
    int bar;
};

void init_foo(struct foo* f) {
    f = malloc(sizeof(struct foo));
    f->bar = 5;
    printf("bar0: %d\n", f->bar);
}

void print_foo(struct foo* f) {
    printf("bar1: %d\n", f->bar);
}

int main() {
    struct foo f;
    init_foo(&f);
    print_foo(&f);
}

Общий результат:

bar0: 5
bar1: 0

Ожидаемый результат:

bar0: 5
bar1: 5

Я не так много раньше имел дело с Cпоэтому, если бы кто-то мог дать объяснение и / или решение этого вопроса, я был бы очень благодарен.

Ответы [ 4 ]

2 голосов
/ 26 октября 2019

Вам нужно избавиться от malloc(), он не принадлежит, поскольку main() уже выделил память для своей локальной переменной f. init_foo() просто необходимо заполнить существующую память. Вызывая malloc(), вы меняете указатель foo* внутри init_foo(), чтобы он указывал на другую память, игнорируя исходную память, которая была передана.

Попробуйте вместо этого:

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

struct foo {
    int bar;
};

void init_foo(struct foo* f) {
    f->bar = 5;
    printf("bar0: %d\n", f->bar);
}

void print_foo(struct foo* f) {
    printf("bar1: %d\n", f->bar);
}

int main() {
    struct foo f;
    init_foo(&f);
    print_foo(&f);
}

С другой стороны, если вы хотите init_foo() выделить память для структуры, сделайте это вместо этого:

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

struct foo {
    int bar;
};

void init_foo(struct foo** f) {
    *f = malloc(sizeof(struct foo));
    if (f) {
        (*f)->bar = 5;
        printf("bar0: %d\n", (*f)->bar);
    }
}

void free_foo(struct foo* f) {
    free(f);
}

void print_foo(struct foo* f) {
    printf("bar1: %d\n", f->bar);
}

int main() {
    struct foo *f;
    init_foo(&f);
    if (f) {
        print_foo(f);
        free_foo(f);
    }
}

Или это:

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

struct foo {
    int bar;
};

struct foo* init_foo() {
    struct foo *f = malloc(sizeof(struct foo));
    if (f) {
        f->bar = 5;
        printf("bar0: %d\n", f->bar);
    }
    return f;
}

void free_foo(struct foo* f) {
    free(f);
}

void print_foo(struct foo* f) {
    printf("bar1: %d\n", f->bar);
}

int main() {
    struct foo *f = init_foo(&f);
    if (f) {
        print_foo(f);
        free_foo(f);
    }
}
2 голосов
/ 26 октября 2019

Не malloc внутри init_foo;пространство уже было выделено вызывающей стороной. Таким образом, вы заполняете пространство, которое вы malloc редактировали, но не пространство, на которое указывает указатель, переданный функции.

2 голосов
/ 26 октября 2019

В main(), f является выделенной версией структуры foo. Вы передали указатель на эту выделенную структуру на init_foo().

Нет необходимости, чтобы f был malloc() 'ed внутри init_foo(). f уже указывает на выделенную структуру.

Я думаю, что если вы просто удалите malloc(), это должно сработать.

1 голос
/ 26 октября 2019

Вы затмеваете struct foo * f.

У вас есть стековая структура struct foo f, определенная в main. Вы передаете указатель на него в функцию init_foo. Однако затем вы немедленно заменяете указатель на структуру выделенной структурой и приступаете к заполнению этой структуры. Исходная структура foo * f, которая была передана в функцию init_foo, поэтому не была изменена.

Затем вы теряете памятьвыйдя из функции init_foo и напечатав неинициализированную структуру.

Вам не нужно выделять память, удалите все. Просто инициализируйте непосредственно в структуру foo * f, которую вы передаете в функцию init_foo.

...