Выделите место для указателя структуры в подфункции - PullRequest
1 голос
/ 02 сентября 2010

Как я могу выделить память для структурного указателя и присвоить значение его члену в подфункции?

Следующий код скомпилируется, но не будет выполнен:

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

struct _struct {char *str;};
void allocate_and_initialize(struct _struct *s)
{
    s = calloc(sizeof(struct _struct), 1);
    s->str = calloc(sizeof(char), 12);
    strcpy(s->str, "hello world");
}
int main(void)
{
    struct _struct *s;
    allocate_and_initialize(s);
    printf("%s\n", s->str);

    return 0;
}

Ответы [ 4 ]

2 голосов
/ 02 сентября 2010

Вы передаете s по значению.Значение s остается неизменным в main после вызова allocate_and_initialize

. Чтобы это исправить, вы должны каким-то образом убедиться, что s в main указывает на блок памяти, выделенный функцией.Это можно сделать, передав адрес s в функцию:

// s is now pointer to a pointer to struct.
void allocate_and_initialize(struct _struct **s)
{
        *s = calloc(sizeof(struct _struct), 1); 
        (*s)->str = calloc(sizeof(char), 12);
        strcpy((*s)->str, "hello world");                                                                                                                                                                      
}
int main(void)
{
        struct _struct *s = NULL;  // good practice to make it null ptr.
        allocate_and_initialize(&s); // pass address of s.
        printf("%s\n", s->str);

        return 0;
}

В качестве альтернативы вы можете вернуть адрес блока, выделенного в функции, обратно и назначить его для s в основном, как было предложенов другом ответе.

1 голос
/ 02 сентября 2010

Вы должны изменить свой код следующим образом:

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

    struct _struct {char *str;};
    void allocate_and_initialize(struct _struct **s)
    {
        *s = (_struct*)calloc(sizeof(struct _struct), 1);
        (*s)->str = (char*)calloc(sizeof(char), 12);
        strcpy((*s)->str, "hello world");
    }
    int main(void)
    {
        struct _struct *s;
        allocate_and_initialize(&s);
        printf("%s\n", s->str);

        return 0;
    }

Причина в том, что вы изменяете адрес указателя, но не «содержимое» указателя. Итак, если вы кодируете в c, вы должны использовать «двойной» указатель. Если вы пишете код на C ++, вы можете использовать ссылку.

1 голос
/ 02 сентября 2010

В вашем примере:

void allocate_and_initialize(struct _struct *s)
{
    s = calloc(sizeof(struct _struct), 1);
    s->str = calloc(sizeof(char), 12);
    strcpy(s->str, "hello world");
}

Назначение s здесь не меняет s в вызывающем абоненте. Почему бы не вернуть его вместо этого?

struct _struct *allocate_and_initialize(void) {
    struct _struct *s;
    s = calloc(sizeof *s, 1);
    s->str = calloc(1, 12); /* sizeof(char) is always 1 */
    strcpy(s->str, "hello world");
    return s;
}

и используйте его таким образом:

struct _struct *s;
s = allocate_and_initialize();
/* use s... */
free(s); /* don't forget to free the memory when you're done */
0 голосов
/ 23 апреля 2012

Вы можете создать объект структуры, затем передать его адрес подфункции, а затем назначить значения в подфункции, создав указатель. Точный код:

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

struct _struct {char *str;};

void allocate_and_initialize(struct _struct *s)
{
    s -> str = malloc(12);
    strcpy(s->str, "hello world");
}

void main(void)
{
    struct _struct _struct;
    allocate_and_initialize(&_struct);
    printf("%s\n", _struct.str);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...