在C语言中从函数中分配结构体

4

我希望你能帮我翻译一下关于IT技术的内容。需要翻译的是有关C语言中分配结构体函数的问题。理想情况下,我希望这个函数可以使用传入的参数填充结构体的字段。

我已经在头文件中定义了这个结构体:

typedef struct {
  char name[NAME_SIZE]; //Employee name
  int birthyear; //Employee birthyear
  int startyear; //Employee start year
} Employee;

这是我目前的函数内容:

void make_employee(char _name, int birth_year, int start_year) {
  Employee _name  = {_name,birth_year,start_year}; //allocates struct with name
} /* end make_employee function */

有没有关于如何完成这个任务的建议?

2
我认为如果您能更详细地描述一下如何使用此函数以及创建的结构体的用途,将会很有帮助。在C语言中,如何分配内存和创建数据结构取决于您计划如何使用它们。 - linuxuser27
4个回答

11
你当前代码的问题在于你创建的结构体是在堆栈上创建的,并且将在函数返回时清除。
struct foo
{
    int a;
    int b;
};

struct foo* create_foo( int a, int b )
{
    struct foo* newFoo = (struct foo*)malloc( sizeof( struct foo ) );
    if( newFoo )
    {
        newFoo->a = a;
        newFoo->b = b;
    }
    return newFoo;
}

这将获取一个堆分配的对象。当然,您需要一个函数来释放该内存,否则这就是内存泄漏。

void destroy_foo( struct foo* obj )
{
    if( obj )
        free( obj );
}

void print_foo( struct foo* obj )
{
    if( obj )
    {
        printf("foo->a = %d\n",obj->a);
        printf("foo->b = %d\n",obj->b);
    }
}

(顺便说一下,这种风格让你部分地迈向了“面向对象”的 C。将一些函数指针加入结构体中(以获得多态行为),你将拥有一些有趣的东西;尽管此时我会提议转向 C++。)


5
你需要返回一个通过malloc分配的指针:
Employee* new_employee(char *_name, int birth_year, int start_year) {
    struct Employee* ret = (struct Employee*)malloc(sizeof(struct Employee));
    ret->name = _name;
    ret->birth_year = birth_year;
    ret->start_year = start_year;
    return ret;
}

还有两件事情:(1) 你应该将name的结构定义改为char*而不是char[NAME_SIZE]。分配字符数组会使结构更大,更不灵活。你真正需要的只是一个char*。并且(2) 将函数定义更改为char*


我不知道你针对第一点提出的建议是什么......只要 NAME_SIZE 是一个合理的大小,就没有必要去正确地动态分配内存并管理它。没有必要让它变得比必要的更加复杂。 - Jeff Mercado
如果对你来说保持简单很重要,那么你知道该怎么做。然而,为只需要5个字节的东西分配200个字节是过度杀伤(而为需要6个字节的东西分配5个字节则是一个错误),这就是为什么你可能想使用指针的原因。 - kelloti
确保在使用完结构体后进行free操作,否则会出现内存泄漏。 - user142162

1
Employee * make_employee(char *_name, int birth_year, int start_year)
{
    Employee *employee;

    if (employee = (struct Employee *)memalloc(sizeof(Employee)) == NULL)
    {
        return NULL;
    }
    else
    {
        strcpy(&(employee->name), _name);
        employee->birthyear = birth_year;
        employee->startyear = start_year;
        return employee;
    }
}

1
为什么make_employee函数返回void?你需要从make_employee函数中返回Employee! 你是否遇到编译器对于x = {a,...}语法的抱怨而感到困惑?那就用冗长的方式来写吧:Emp e; e.field1 = a; ... 你是否遇到奇怪的覆盖/虚假数字问题?如果你在函数中分配了一个结构体,那么它会在函数返回后变得无效(且容易被覆盖)!为了解决这个问题,你可以选择以下方式之一: 返回结构体的副本(对于小型结构体而言是可以的): Employee make_emp(int a){ Emp emp; //分配临时结构体 emp.filed1 = a; //初始化字段 return emp; //返回副本 }
或者在堆上分配结构体,并通过引用(即指针)进行处理: Employee* make_emp(int a){ Emp* emp = malloc(sizeof(Emp)); //在堆上分配结构体并获取其引用 emp->filed1 = a; //初始化 return emp; //返回引用 } 在这种情况下,不要忘记在使用完Employee后调用free()释放内存!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接