-1

This question is not an exact duplicate of this. The most popular answer here says that it was not guaranteed that the memory location would be preserved but by accident it did. Where I got this piece of code from, it says clearly that the string variable will be preserved.

Consider the following code:

#include<stdio.h>

char *getString()
{
    char *str = "abc";
    return str;
}     

int main()
{
   printf("%s", getString());  
   getchar();
   return 0;
}

This code compiles and runs without any errors. The pointer char* str is not defined as a static variable. Yet the variable seems to be preserved even after the function returns.

Please explain this behavior.

I do not understand why this question got a negative vote even though it's not answered yet or marked as duplicate.

TARS
  • 47
  • 5
  • 1
    Possible duplicate of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – John3136 Jun 29 '18 at 03:41
  • [This answer](https://stackoverflow.com/a/2589974/1553090) mentions that string literals have static storage duration. Although I can't seem to find that clause in a quick skim through the standard. Personally, I've always treated them as static `const char*` values. – paddy Jun 29 '18 at 03:47
  • 1
    @John3136: This is not an exact duplicate. In the link you send it says that the memory got preserved by accident but in my code it seems like it's guaranteed that it will be preserved. – TARS Jun 29 '18 at 03:51
  • You forgot to include the `return` in your `getString()` btw. – O.O.Balance Jun 29 '18 at 04:49
  • @O.O.Balance: Okay I will add it now. Thanks – TARS Jun 29 '18 at 04:55
  • 1
    The source you have given also makes a distinction between the case of using an array of `char` and using a pointer to `char`, claiming one is fine, and the other is not. Might be worth including in the question. – O.O.Balance Jun 29 '18 at 04:57
  • 1
    @John3136 this is not a duplicate of that – M.M Jun 29 '18 at 05:54
  • 1
    [String literals: Where do they go?](https://stackoverflow.com/questions/2589949/string-literals-where-do-they-go) – Lundin Jun 29 '18 at 06:59

3 Answers3

2

char *getString() ... char *str = "abc";

You are making some confusion. getString() creates a variable in the stack, and makes it point to a literal string. That literal can be anywhere, and will stay always there; depending on the compiler, it can be in RAM initialized at startup, or it can be in read-only memory. OK: If it is in RAM, perhaps you can even modify it, but not in normal (legal) ways - we should ignore this and think at the literal as immutable data.

The point above is THE point. It is true that the string "is preserved". But it is not true that an automatic variable is preserved - it can happen, but you should not rely on that, it is an error if you do it. By definition, an automatic variable gets destroyed when the function returns, and be sure that it happens.

That said, I don't see how you can say that the variable is preserved. There is no mechanism in C to peek at local variables (outside the current scope); you can do it with a debugger, especially when the active frame is that of getString(); maybe some debugger lets you to look where you shouldn't, but this is another matter.

EDIT after the comment

Many compilers create auto (local) variables in the stack. When the function returns, the data on the stack remains untouched, because clearing/destroying the stack is made by simply moving the stack pointer elsewhere. So the affirmation "the variable seems to be preserved" is correct. It seems because actually the variable is still there. It seems because there is no legal way to use it. But even in this situation, where the variable is still there but hidden, the compiler can decide to use that room for something else, or an interrupt can arrive and use that same room. In other words, while the auto variable is in scope it is guaranteed to be "preserved", but when it falls out of scope it must be considered gone.

There are situation where one can write code that refers to variables fallen out of scope: these are errors that the compiler should (and sometimes can) detect.

I said that often auto variables go in the stack. This is not always true, it depends on architecture and compiler, but all the rest is true and it is dictated by the language rules.

1

The address of str may change but the thing it points to (once initialised) will not.

Note that in this simple example you probably won't see changes. If you call getString a few times from different stack depths and show &str you will see what I mean.

char *getString()
{
    char *str = "abc";
    printf("%p", &str);
    return str;
}     

    int main()
    {
       printf("%s", getString());  

       stackTest();
       getchar();
       return 0;
    }
    void stackTest()
    {
      char blob[200];
      int  x=0;
     printf("%s", getString());  
    }

*(I have not tested this and my unused stack variables might get optimised away depending on your compiler & settings)

LoztInSpace
  • 5,584
  • 1
  • 15
  • 27
  • @LoztlnSpace: So you mean to say that the value inside the memory location pointed by `str` will be stored in a read only memory and the pointer itself will be stored in stack which probably will get cleared once the function returns? – TARS Jun 29 '18 at 05:54
  • @TARS yes, it is almost so. But: str points somewhere, perhaps NOT in read-only memory (PCs don't have "true" read-only memory). And the stack contents, probably, will be destroyed upon a subsequent invocation of any subroutine, not upon returning from getString(). But this implementation dependent. – linuxfan says Reinstate Monica Jun 29 '18 at 06:04
  • So if I store the address returned by the function in some other pointer variable say `int *a` inside main and access it multiple times to print the contents of the location pointed by `a`, it is guaranteed to print `abc` no matter what? – TARS Jun 29 '18 at 06:15
  • Yes to the "read only" (but it's not read-only) and Yes to getting the consistent address, but don't store a `char*` in an `int*`. You can (but why would you). If you do, sometimes alignment issues with various types might bite you. – LoztInSpace Jun 29 '18 at 09:15
0

C 2011 (draft N1570) clause 6.4.5, paragraph 6 describes how a string literal in source code becomes a static object:

The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence.

Thus, in char *str = "abc";, str is initialized to point to a static array containing the characters a, b, and c, and a null character.

Then return str; returns the value of this pointer.

Finally, printf("%s", getString()); passes the value of the pointer to printf. At this point, the str object is gone (in the C model of computation). It no longer exists. We have the value it was used to hold, but the str object itself is gone. However, the value points to a static object, the array of characters, and printf reads that array and prints it.

So, the title of your question is incorrect. The non-static pointer variable declared inside the function was not preserved. All that was preserved was the static array of characters and its address.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312