Иерархия функций и проблема инициализации C-указателей - PullRequest
0 голосов
/ 19 августа 2011

Я превращаю свой проект в C из C ++, и все шло гладко, так как я с самого начала не использовал много функций C ++. Но я столкнулся с особой проблемой, которую мне удалось воспроизвести в небольшой тестовой программе. Это не имеет смысла для меня, поэтому я попытаюсь объяснить с помощью кода.

typedef struct foo
{
    int num1;
    float num2;
    char* name;
}foo;

//This function allocates and initializes a foo object
foo* Initfoo()
{
    foo* f = malloc(sizeof(foo));
    f->num1 = 1024;
    f->num2 = 3.14;

    f->name = malloc(100);
    strcpy(f->name,"eleos re paidia");

    //Just before returning here by checking the f pointer we can see
    // it is initialized correctly
    return f;
}



 void afunctest(foo* f)
 {
    ///... suppose this function does stuff before ...

    //here it initializes the foo pointer
    f = Initfoo();
    ///...and after here suppose the function also does more stuff..

    //by checking at this point in the program the pointer is still initialized 
    //correctly to   what InitFoo initialized it to
    int asd =5;
 }


int main()
{

    foo* f = 0;

    //should do stuff and also initialize the foo* f
    afunctest(f);

    //when we check here the pointer f is still 0 as if afunctest() function never ran
    int asd = 5;

    return 0;
}

Итак, в двух словах, мы объявляем указатель foo и инициализируем его нулем. Затем мы передаем этот указатель в функцию afunctest (), которая должна что-то делать, а также инициализировать ее для дальнейшего использования. Внутри функции afunctest () она, кажется, правильно инициализируется, но как только мы вернемся к main (), она все равно будет иметь значение 0, как если бы функция никогда не выполнялась.

Сначала я подумал, что это действительно сложная ошибка в моей исходной программе, поскольку она стала довольно сложной, но возможность ее воспроизвести здесь означает, что я упускаю что-то фундаментальное в использовании указателей в C по сравнению с C ++. Можете ли вы, люди, указать на это? Что я делаю неправильно? Заранее спасибо за любые отзывы.

P.S .: Мой компилятор - GCC под Windows 7.

Ответы [ 3 ]

2 голосов
/ 19 августа 2011

Вы меняете локальную копию f.Это не имеет никакого эффекта для вызывающего абонента.

void afunctest(foo* f)
{
    f = Initfoo(); /* No effect for the caller of afunctest
}

Попробуйте что-то вроде этого:

void afunctest(foo **f)
{
    /* ... */
    *f = Initfoo();
}

/* In main. */
foo* f = 0;
functest(&f);

Кстати, есть также C FAQ: Pass указатель Init .

1 голос
/ 19 августа 2011

Решение на самом деле простое - помните, что C всегда проходит по значению, поэтому, когда вы устанавливаете f в функции afunctest, которая НЕ обновляет ваш f в основной функции.

Для этого вам нужно использовать ** f так:

void afunctest(foo** f)
 {

    //here it initializes the foo pointer
    *f = Initfoo();

 }

и назовите это так:

int main()
{

    foo* f = 0;

    //should do stuff and also initialize the foo* f
    afunctest(&f);

    return 0;
}
1 голос
/ 19 августа 2011

C передается значением . Если вы хотите изменить f из afunctest(), вам нужно будет передать ему указатель и манипулировать значением, на которое оно указывает к.

Например:

#include <stdio.h>

static void fn (int x, int *y) {
    x = 42;     // Changes local copy of x, doesn't affect a.
    *y = 42;    // Changes value *pointed to* by local y (which is b in caller).
}

int main (void) {
    int a = 1;
    int b = 1;
    fn (a, &b); // Pass a and *address of* b.

    printf ("%d %d\n", a, b);
    return 0;
}

приводит к выводу:

1 42

С точки зрения имеющегося у вас кода это будет:

void afunctest (foo **f) {
    *f = Initfoo();
}

int main (void) {
    foo* f = 0;
    afunctest (&f);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...