4

Apologies if this is a "basic" question, but I am new to C and can't find the answer. My question is regarding the need to malloc a variable and return its pointer within a function, compared with creating the variable within the function and returning the result.

The first issue that comes to mind is that any variables declared within the scope of the function will be destroyed once the function terminates; so why is it then that the following is valid:

int add(int a, int b)
{
    int result;
    result = a + b;
    return result;
}

But the following is not?

char *concat(char* a, char* b)
{
    char result[10];
    strcat(result, a);
    strcat(result, b);
    return result;
}

The warning you get is that you are returning an address to a local variable, but this is what we are also doing in the first function? Does the behaviour differ depending on the type?

For a more real example, I'm very confused regarding which of the following 2 functions I should be using, as they both work perfectly well for my program:

struct Card *card_create(enum Rank rank, enum Suit suit)
{
    struct Card *card = malloc(sizeof(struct Card));
    if(card == NULL) {
        fprintf(stderr, "malloc: %s", strerror(errno));
        return NULL;
    }
    card->rank = rank;
    card->suit = suit;
    return card;
}

Or:

struct Card card_create(enum Rank rank, enum Suit suit)
{
    struct Card card;
    card.rank = rank;
    card.suit = suit;
    return card;
}

Again, sorry if this is a nooby question, but I'd really appreciate an explanation. Thanks!

Cristian
  • 6,765
  • 7
  • 43
  • 64
  • `The warning you get is that you are returning an address to a local variable, but this is what we are also doing in the first function?` No it is not. The first function returns a value of local variable, while the second returns the address of a local variable - different things, first makes sense, the second does not. – Wojtek Surowka Jul 15 '14 at 22:23
  • This is undoubtedly a duplicate -- the issue is which question is it a good duplicate of. – Jonathan Leffler Jul 15 '14 at 22:30
  • [This](http://stackoverflow.com/questions/12380758/c-error-function-returns-address-of-local-variable) (or just search for “returning address of local variable” or the like) and perhaps [this](http://stackoverflow.com/questions/9653072/return-a-struct-from-a-function-in-c) for returning a structure by value. Note, that your array decays to a pointer in the return statement, but the structure doesn't. And maybe it helps to note, that the address of an object is a value, but a value isn't necessarily an address (and is never an object, but an object may _have_ a value). – mafso Jul 15 '14 at 22:43

4 Answers4

8

In your add() function, you return the value that is held (until the function exits) in its local variable result. The storage for that variable is no longer available once the function returns, but the value that was stored there is just a number, not in itself dependent on that storage.

In your concat() function, the expression result evaluates to a pointer to the local storage for an array of 10 char. You can still return the pointer's value, but once the function exits the meaning of that value is no longer defined.

So, no, the behavior of returning a value does not itself differ between those cases, but the usefulness -- indeed the risk -- associated with doing so varies greatly.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
4

Does the behaviour differ depending on the type?

Kind of. When you return something in C, you return the value, not a pointer to the value or anything that depends on any variables still existing. However, there's an unrelated rule that says that in almost all contexts, a value of array type is implicitly converted to a pointer to the array's first element. Thus, the second code snippet is returning a pointer into the array, while the first snippet just returns an int.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Thanks very much for your answer. Am I right in saying then that a function needs only ever return a pointer if the value to return is a pointer/array? So, in the example of the 2 structs, the first code snippet (without the use of pointers) would be best? – Cristian Jul 15 '14 at 22:27
  • @Cristian: I would probably use the one that returns a `struct Card` instead of a `struct Card *`. (You may have gotten the order of the snippets switched.) – user2357112 Jul 15 '14 at 22:29
2

Very interesting question

When a function return local variable as vlue, A new variable will be created and stored in CPU registers( depends on compiler). After that, local variable will be freed.

 int add(int a, int b)
 {
     int result;
     result = a + b;

     return result; // 1. A new int variable will be created and stored in CPU registers (depends on Compiler)

     // 2. result will be freed at the end of function
 }

In CPP, the process is very similar to C, card constructor will be called twice

 struct Card card_create(enum Rank rank, enum Suit suit)
 {
     struct Card card;
     card.rank = rank;
     card.suit = suit;

     return card; // 1. New Card object will be created and stored in CPU register(Depends on compiler)

     // 2. card will be freed at the end of function
 }

Hope this help.

Hoang Pham
  • 136
  • 1
  • 4
1

In the first code snip, the value of an int variable is being returned. Very OK.

In the second code snip, the address of a local (stack) variable is being returned. Not OK.


And, perhaps the line:

char[10] result;

would be better as:

char result[10];

If the second example declared result as follows:

char result;

then the value in result could be returned:

return(result);

However, the second example defines result as an array of char; making result a pointer to the beginning of this array. Hence, the true value of result in the second example is an address to local stack memory (which disappears when the function scope terminates).

The first example captures the value of result (an integer value) and sends the value back to the caller, (not the address of the value in the function's local scope).

Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28