6

Here is the code,

char *foo()
{
    static char s[10] = "abcde";
    return s;
}

char *bar()
{
    char *c = foo();
    return c;
}

int main()
{
    printf("%s\n", bar()); 
}

Typically, it is wrong to return a local pointer as I did in bar, but now c points to a static var returned by foo, would it be correct to return a local var c in bar?

I tried, it printf the right value, but I don't understand how it works. I thought, when bar() finishes, the var c should vanish, which should make printf print undefined stuff, right?

Follow Up

char *c is a local var, if char *c = "abcde";, I assume this: c is a local var which resides in the function's stack, while "abcde" is a constant var which resides in the constants-area (part of the heap?), so when bar() finishes, c vanishes, but "abcde" still remains in the heap, right?

Alcott
  • 17,905
  • 32
  • 116
  • 173
  • In this question, won't it be like `static char *foo()` instead of `char *foo()` as the return type of foo is `static char *`. It might throw: **warning: no previous prototype for ‘foo’ [-Wmissing-prototypes]**. – Dr. Essen Apr 04 '18 at 07:57

4 Answers4

10

Variable c is only a pointer. It is not wrong to return a local pointer from a function, you do it all the time. For example, when you store a result of malloc in a pointer, the pointer is local, but the storage it points to is not. It is, however, wrong to return a pointer to a local storage. Since in your example c never points to a locally allocated data, your code works correctly as written.

EDIT (in response to the Follow Up)

"abcde" is a constant var which resides in the constants-area (part of the heap?)

The constants area is not usually part of the heap, it is either a separate arrea, usually adjacent to the area where the machine code of your program is stored.

c vanishes, but "abcde" still remains in the heap, right?

"abcde" remains in the constants area, not in the heap, but the concept is correct: the pointer to that constant remains valid throughout the entire run-time of your program.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Aha, yes. But sorry, what I want to is just another one, post edit. – Alcott Feb 24 '12 at 01:14
  • @Alcott I edited the answer in response to the follow up. – Sergey Kalinichenko Feb 24 '12 at 01:21
  • BTW, where could I get more details about constants area ? – Alcott Feb 24 '12 at 01:33
  • Start from here http://en.wikipedia.org/wiki/.bss and then here http://en.wikipedia.org/wiki/Data_segment – Metz Feb 24 '12 at 01:39
  • @Alcott [here](http://shareprogrammingtips.com/c-language-programming-tips/structure-of-a-c-program-in-memory-how-heapstackdata-and-code-segments-are-stored-in-memory/) is a quick reference explaining the various memory segments of a running program. Character constants are usually stored in the code segment, although this is architecture dependent: sometimes, character constants get copied to the data segment upon the program start-up. – Sergey Kalinichenko Feb 24 '12 at 01:44
1

The value of c is returned, which is foo() which is s which is the address of "abcde". What vanish after bar returns is the space in which that value was stored when you did char *c = foo();.

So, yes, it's correct.

Metz
  • 675
  • 1
  • 9
  • 17
  • So when `c` vanishes, but "abcde" remains, so the address of `"abcde"` is valid, right? – Alcott Feb 24 '12 at 01:16
  • I think you need to understand what it means that a variable "vanishes" after a function returns. Have a look at the assembly code, compiling with gcc test.c -O0 -S. – Metz Feb 24 '12 at 01:27
1

Your intuition is correct, but the issue you seem to be having is this:

There are three types of storage in C,

Automatic (the normal local storage) Which lives on the stack and pointers to this data are no longer valid after the return of the function.

Dynamic (think malloc) Which lives in the heap and pointers to this data are no longer valid after free() is called.

Static Which lives in the data segment (and so it doesn't disappear).

Since s is a static variable it lasts for the entire lifetime of the program. And so, no it will not vanish when foo returns.

Edit: I should add that there is also register, but that is largely ignored by most compilers.

Avi
  • 1,231
  • 10
  • 23
  • `register` isn't ignored. Taking the address of a `register` variable is a constraint violation, and this is nowadays just its purpose, telling the compiler to be warned if you take the address of such a variable. – Jens Gustedt Feb 24 '12 at 07:31
  • That is true. However, it's probably around for historical reasons. See http://stackoverflow.com/questions/578202/register-keyword-in-c – Avi Feb 24 '12 at 07:35
  • no it is just an mean for optimization as e.g the `restrict` keyword. And it also just avoids the error which you are talking about in your answer. You can't take its address, so you will never be tempted to return that to the caller. If it would be just for historical reasons, the committee would probably declared it obsolete since then, which it did for some features. – Jens Gustedt Feb 24 '12 at 08:17
  • Let's be clear, the worldwide standard for C is ANSI C which is from the 70s. Computers and especially compilers were much more primitive then. register had it's place then. As for the notion that register is there to keep the programmer from making some dumb mistake. Well, first that goes contrary to the c philosphy and second it only there because data in a register can't have it's address taken. Also, the C++ people want to depricate it. See http://stackoverflow.com/questions/1256246/address-of-register-variable. – Avi Feb 24 '12 at 08:25
  • You are mistaken, ANSI C was first standardized in 1989, and the aspect of standardization really came as a big advantage, then. And since you speak of standard (and not of market share or things like that) the current standard for C is C11 from December last year. It was given by ISO, which is the international standards organization. – Jens Gustedt Feb 24 '12 at 10:05
  • You are correct that I had the date wrong. However, my point was that ANSI C is supported by every compiler used these days. Whereas C99 or C11 aren't supported at all in some compilers and even GCC doesn't support all of these various standards' features. In fact, if I may borrow a line from your own project, "P99 heavily depends on a decent support for C99 of compilers." At this point this is a not a constructive conversation and so I will end it here. – Avi Feb 24 '12 at 17:46
0

static local variable inside a function will stay in memory till the application ends, and does not go away when the function returns. That is why having a pointer to the static variable gives you valid data in printf even outside of the function foo.

If the local variable is not static, the same test would fail as the variable goes away as the function returns.

Kamyar Souri
  • 1,871
  • 19
  • 29