简体   繁体   中英

define a function returning struct pointer

Please bear with me, im from other language and newbie to c and learning it from http://c.learncodethehardway.org/book/learn-c-the-hard-way.html

struct Person {
    char *name;
    int age;
    int height;
    int weight;
};

struct Person *Person_create(char *name, int age, int height, int weight)
{
    struct Person *who = malloc(sizeof(struct Person));
    assert(who != NULL);

    who->name = strdup(name);
    who->age = age;
    who->height = height;
    who->weight = weight;

    return who;
}

I understand the second Person_create function returns a pointer of struct Person. I don't understand is(may be because im from other language, erlang, ruby), why does it define it as

struct Person *Person_create(char *name, int age, int height, int weight)

not

struct Person Person_create(char *name, int age, int height, int weight)

and is there other way to define a function to return a structure?

sorry if this question is too basic.

It is defined so because it returns a pointer to a struct, not a struct. You assign the return value to a struct Person * , not to struct Person .

It is possible to return a full struct, like that:

struct Person Person_create(char *name, int age, int height, int weight)
{
    struct Person who;
    who.name = strdup(name);
    who.age = age;
    who.height = height;
    who.weight = weight;
    return who;
}

But it is not used very often.

The function returns who , which is a struct Person * - a pointer to a structure. The memory to hold the structure is allocated by malloc() , and the function returns a pointer to that memory.

If the function were declared to return struct Person and not a pointer, then who could also be declared as a structure. Upon return, the structure would be copied and returned to the caller. Note that the copy is less efficient than simply returning a pointer to the memory.

The Person_create function returns a pointer to a struct Person so you have to define the return value to be a pointer (by adding the *). To understand the reason for returning a pointer to a struct and not the struct itself one must understand the way C handles memory.

When you call a function in C you add a record for it on the call stack . At the bottom of the call stack is the main function of the program you're running, at the top is the currently executing function. The records on the stack contain information such as the values of the parameters passed to the functions and all the local variables of the functions.

There is another type of memory your program has access to: heap memory. This is where you allocate space using malloc , and it is not connected to the call stack.

When you return from a function the call stack is popped and all the information associated with the function call are lost. If you want to return a struct you have two options: copy the data inside the struct before it is popped from the call stack, or keep the data in heap memory and return a pointer to it. It's more expensive to copy the data byte for byte than to simply return a pointer, and thus you would normally want to do that to save resources (both memory and CPU cycles). However, it doesn't come without cost; when you keep your data in heap memory you have to remember to free it when you stop using it, otherwise your program will leak memory.

Structs are not pointers (or references) by default in C/C++, as they are for example in Java. Struct Person Function() would therefor return struct itself (by value, making a copy) not a pointer.

You often don't want to create copies of objects (shallow copies by default, or copies created using copy constructors) as this can get pretty time consuming soon.

To copy the whole struct and not just pointer is less efficient because a pointer's sizeof is usually much smaller than sizeof of a whole struct itself.

Also, a struct might contain pointers to other data in memory, and blindly copying that could be dangerous for dynamically allocated data (if a code handling one copy would free it, the other copy would be left with invalid pointer).

So shallow copy is almost always a bad idea, unless you're sure that the original goes out of scope - and then why wouldn't you just return a pointer to the struct instead (a struct dynamically allocated on heap of course, so it won't be destroyed like the stack-allocated entities are destroyed, on return from a function).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM