45
#include <stdio.h>

int foo1(void)
{
    int p;
    p = 99;
    return p;
}

char *foo2(void)
{
    char buffer[] = "test_123";
    return buffer;
}

int *foo3(void)
{
    int t[3] = {1,2,3};
    return t;
}

int main(void)
{
    int *p;
    char *s;

    printf("foo1: %d\n", foo1());
    printf("foo2: %s\n", foo2());
    printf("foo3: %d, %d, %d\n", p[0], p[1], p[2]);
    return 0;
}

When I compile this with gcc -ansi -pedantic -W -Wall the compiler issues warning messages for foo2() and foo3():

warning: function returns address of local variable

I thought it is not allowed to return a local variable, but foo1() works fine and it seems there is a huge difference between returning pointer to a local object and the object itself.

Could anybody shed some light on this issue? Thanks in advance!

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Mark
  • 1,751
  • 3
  • 14
  • 14

4 Answers4

37

The issue here is that when you create the local variable it is allocated on the stack and is therefore unavailable once the function finishes execution (implementation varies here). The preferable way would be to use malloc() to reserve non-local memory. the danger here is that you have to deallocate (free()) everything you allocated using malloc(), and if you forget, you create a memory leak.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
kelloti
  • 8,705
  • 5
  • 46
  • 82
28

For foo1(), you return a copy of the local variable, not the local variable itself.

For the other functions, you return a copy of a pointer to a local variable. However, that local variable is deallocated when the function finishes, so you end up with nasty issues if you try to reference it afterwards.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Cam
  • 689
  • 4
  • 8
  • This should be the accepted answer as the currently accepted answer isn't really answering the question. – rjcarr May 18 '22 at 06:51
6

Any variable has some space in the memory. A pointer references that space. The space that local variables occupies is deallocated when the function call returns, meaning that it can and will be reused for other things. As a consequence, references to that space are going to wind up pointing to something completely unrelated. Arrays in C are implemented as pointers, so this winds up applying to them. And constant arrays declared in a function also count as being local.

If you want to use an array or other pointer beyond the scope of the function in which it is created, you need to use malloc to reserve the space for it. Space reserved using malloc will not be reallocated or reused until it is explicitly released by calling free.

Keith Irwin
  • 5,628
  • 22
  • 31
  • 3
    +1. In practive this means you need to allocate a return value on the heap rather on the stack. You need to use malloc or similair on the "arrays" you want to return. Or better off, take a pointer to a buffer + buffer length as parameters. – stefan Jan 28 '11 at 02:48
  • @stefan: Yeah, that's a good point. I've added more suggestions for how to solve this to the answer. – Keith Irwin Jan 28 '11 at 02:50
  • 1
    'Arrays in C are implemented as pointers' is an over-simplification; it is border-line acceptable for the context, but there are major differences between arrays and pointers (as well as lots of similarities). – Jonathan Leffler Jan 28 '11 at 03:14
  • @Jonathan Leffler: I'm not aware of any differences. They're treated the same by the type system and references and dereferences compile to the same assembly whether it's an array reference or a pointer. If you have int *ip, then *ip and ip[0] are interchangeable. So too are *(ip+1) and ip[1]. It may just be something I'm unaware of, but how are arrays and pointers different in C? – Keith Irwin Jan 28 '11 at 19:32
  • 1
    Consider: `char *a = "a"; char b[] = "b"; char *c; char d[] = "d";`. You can write: `c = a;` and `c = b;`, but you cannot write `b = a;` or `b = d;`, which is an important difference between arrays and pointers. – Jonathan Leffler Jan 28 '11 at 20:45
  • @Jonathan: Ah, you're right. So they aren't actually treated identically by the type system. Thanks for the example. – Keith Irwin Jan 29 '11 at 01:08
0

Yes you are returning an array, which is actually a pointer behind the scenes, to the address of the memory location where the contents of the variable you've initialised is stored. So it's warning you that it might not be quite as useful to return such a result, when you might really mean one of the array values instead.

evandrix
  • 6,041
  • 4
  • 27
  • 38