michalska7 michalska7 - 2 months ago 7
C Question

C passing by reference (pointer) crashes

I have this code:

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

typedef struct employee {
char *name;
double salary;
} employee;

void new_employee (employee *person, char *name, double salary) {
person = malloc(sizeof(employee));
person->name = malloc(strlen(name) + 1);
strcpy(person->name, name);
person->salary = salary;
printf("Employee: name=%s salary=%f\n", person->name, person->salary);
}


int main(int argc, char *argv[])
{
employee *bob = 0;
new_employee(bob, "Bob Doe", 1000);
printf("Employee: name=%s salary=%f\n", bob->name, bob->salary);
return 0;
}


I'm not sure what is wrong, but I can use the struct in new_employee, but it breaks when I try to use it from main. Basically the first printf works the the second one crashes. I think that main is not getting bob updated, but I am using a pointer, so it should be pass by reference.

Answer

Your problem is that new_employee() can't change the bob pointer in main. You could make it work by using a double pointer. You can think of the pointer meaning that you're passing the struct by reference, but the pointer value itself is still passed by value. If you pass a pointer to the pointer, then you could change the pointer bob back in main.

However, I think the better solution is to have new_employee() return the pointer. Then in main you just assign the result to bob. Like this:

employee *new_employee (char *name, double salary) {
    employee *person = malloc(sizeof(employee));
    person->name = malloc(strlen(name) + 1);
    strcpy(person->name, name);
    person->salary = salary;
    printf("Employee: name=%s salary=%f\n", person->name, person->salary);
    return person;
}


int main(int argc, char *argv[])
{
    employee *bob = 0;
    bob = new_employee("Bob Doe", 1000);
    printf("Employee: name=%s salary=%f\n", bob->name, bob->salary);
    return 0;
}

Also keep in mind that you should be doing error checking (for example, what if malloc() fails?) and you also should use free() on bob->name and bob before the program ends. If you allocate a lot of new employees and don't free() them when you're done, you could use up a lot of memory for no reason (memory leak).

You could make a free function such as:

void free_employee(employee *person) {
  free(person->name);
  free(person);
}