Search code examples
cpointersstructdynamicreturn

Return a pointer to this new structure in the b parameter?


I'm trying to implement a void initBook(char *t, int y, BookType **b) function that dynamically allocates a new BookType structure, initializes the new structure’s fields to the values found in the t and y parameters, and returns a pointer to this new structure in the b parameter. I'm confused as to how I would do the last part where I have to return a pointer and would appreciate some help. I also thought I couldn't return values if a function is void? When I try compiling, I get the warning

'return' with a value, in function returning void.

Unrelated, but I also get the error

'*b' is a pointer; did you mean to use '->'? for the line *b->year = y;

which confuses me because I literally wrote an arrow. Does anyone know why I'm still getting this error?

Book.c

void initBook(char *t, int y, BookType **b){
    *b = malloc(sizeof(BookType));
    strcpy((*b)->title, t);
    *b->year = y;
    return b;
}

defs.h

typedef struct{
    int id;
    char *title; 
    int year;
} BookType;

Solution

  • You have two choices:

    1. You simply set the values for *b as you are doing, and return nothing,
    void initBook(char *t, int y, BookType **b) {
        /* Assume BookType was malloc'ed outside of this function. */
        (*b)->title = malloc(strlen(t) + 1);
        strcpy((*b)->title, t);
        (*b)->year = y;
        return;
    }
    
    1. Don't pass b as an argument, but declare the function to return a pointer to it:
    BookType* initBook(char *t, int y) {
        BookType *b = malloc(sizeof(BookType));
        b->title = malloc(strlen(t) + 1);
        strcpy(b->title, t);
        b->year = y;
        return b;
    }
    

    A few comments on the above. In the first form, you could malloc if you want, but usually with that approach, it is assumed the malloc is done outside of the function (so you will remember to do the free there as well).

    Also, in the first form, C convention is to put the returning arguments to the left, similar to assignment.

    The second form is more like a "factory". The function mallocs and initializes the object (though the code does not set a value for id). But you will still need to free the pointer when you are done.

    I've added a malloc for the title variable (per comment by Martin James that it is uninitialized). However, I would recommend that the title variable in the struct definition rather have some fixed maximum length (unless for your application that is not possible, that you really must allow it to be any length, in which case you will have to remember to free it later).