user604960
user604960

Reputation: 65

Allocate struct from function in C

I'm having issues writing a function that allocates a struct in C. Ideally, I want to have the function fill the fields of the struct with parameters passed into it.

I have defined the struct in my header file like so:

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

And this is what I have for my function currently:

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 */

Any advice on how to accomplish this?

Upvotes: 4

Views: 19595

Answers (4)

Thuski
Thuski

Reputation: 11

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;
    }
}

Upvotes: 1

dicroce
dicroce

Reputation: 46770

The problem with your current code is that the struct your creating is created on the stack and will be cleaned up as soon as the function returns.

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;
}

This will get you a heap allocated object. Of course, you'll need a function to free that memory or this is a memory leak.

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);
    }
}

(btw, this style gets you part of the way toward an "object oriented" C. Add some function pointers to the struct (to get polymorphic behavior) and you have something interesting; though I'd argue for C++ at that point.)

Upvotes: 11

hugomg
hugomg

Reputation: 69934

  1. Why does the make Employee return void? You need to return the Employee from the make_employee function!

  2. Are you having trouble with the compiler complaining about the x = {a,...} syntax? Write it the long way then: Emp e; e.field1 = a; ...

  3. Are you having weird overwriting / bogus numbers problems? If you allocate a struct in the function it will become invalid (and prone to being overwriten) as soon as the function returns! To go around this you either have to:

    • Return a copy of the struct (this is OK for small structs):

      Employee make_emp(int a){
          Emp emp; //Allocate temporary struct
          emp.filed1 = a; //Initialize fields;
          return emp; // Return a copy
      }
      
    • Allocate the struct in the heap instead and deal with it through references (ie.: pointers) instead:

       Employee* make_emp(int a){
          Emp* emp = malloc(sizeof(Emp)); //Allocate the struct on the heap
                                          //And get a reference to it
          emp->filed1 = a; //Initialize it
          return emp; //Return the reference
       }
      

      Don't forget to free() the Employee after you are done with it in this case!

Upvotes: 1

kelloti
kelloti

Reputation: 8951

You have to return a pointer allocated via 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;
}

two more things: (1) you should make the struct definition of name a char* instead of char[NAME_SIZE]. Allocating a char array makes the struct much bigger and less flexible. All you really need is a char* anyway. And (2) change the function definition to char*.

Upvotes: 5

Related Questions