6

I am beginner in C. I have one program as below:

int main()
{
    char* func();
    char *c;
    c = func();
    printf("%s", c);
}

char* func()
{
    char *ptr = "OK";
    return ptr;
}

As we all know, ptr is a local variable of func() and is a pointer. The scope is local. But when ptr is returned to the caller, main, it is still valid and when c is printed, it prints "OK".

How is this possible? In which memory segment is ptr stored; stack, or heap?

Ry-
  • 218,210
  • 55
  • 464
  • 476
ravi ravi
  • 87
  • 1
  • 1
  • 2

8 Answers8

9

This is what's going under the hood when using pointer (Note that pointer is just like what the name implies, something like a finger pointing to something).

Let's break down your codes and understand it bit by bit. In your main function, you declared a character pointer *c

char *c;

Then you did this:

c = func();

which tells the c pointer to point to whatever this func() is pointing to.

Let's look at your function

char* func()
{
    char *ptr = "OK";
    return ptr;
}

The first line, again, declare a character pointer ptr, and assigned "OK" to that address (Note: pointer just points to some memory address). So now, that address contains the string "OK" (or more precisely, an array of char).

Then you return ptr, which is the address of where "OK" is located at. Note that because ptr is declared in func(), it is a local variable. Hence, once return, it is removed from the stack (poof! Gone).

However, because in your main():

c = func(); 

The variable c is pointing to the address of where "OK" is stored. Hence, even though the variable ptr no longer exist, the variable c knows where it is, and can still access "OK".

To answer your question:

  • ptr is stored at stack
  • and ptr is pop off from the stack when you exit the func()
Arial
  • 4,844
  • 2
  • 18
  • 17
4

Let us forget about stack/heap for a moment. Let's talk C.

The local variable ptr doesn't exist outside func, so the caller cannot and should not refer to it.

But C doesn't do pass by reference. Everything is passed by value. func returns the value stored in ptr to its caller. Much like you would return the value of an int or any other type.

So for your example, ptr's value is the address of a string literal called "OK". And string literals are valid during the entire scope of the program. So func returns the address of a string literal, which is allowed to be dereferenced anywhere in the program.

To be more clear, func is equivalent to:

const char * func (void)
{
  return "OK";
}

This is why everything works out fine.

It is also useful to know that while the following is OK:

const char * func (void)
{
  char *ptr = "OK";
  return ptr;
}

This is not:

const char * func (void)
{
  char ptr[] = "OK";
  return ptr;
}

It is not OK because now you're returning a pointer to an array which is local to func.

One more small point. It should be: const char * func (), because "OK" is not allowed to be modified.

Community
  • 1
  • 1
ArjunShankar
  • 23,020
  • 5
  • 61
  • 83
3

When you're calling the function, all its local variables and return address pushes onto the stack. So ptr will be on the stack, but "OK"-string in constant data section. When you're returning from func, value of ptr is assigned to c variable, ptr is no longer exists (actually, exists), but its value stored in c.

flamingo
  • 496
  • 5
  • 14
2

The text "OK" is stored in the constant data section of your executable (which is loaded into memory when your process is started). Although ptr is a local variable, the compiler initialises it to point to the "OK" that is stored elsewhere. When you return ptr to the caller, the pointer still points to the same "OK".

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • the C standard doesn't use the term "constant data section" – user411313 Jul 14 '12 at 05:18
  • While that is true, it's more helpful than not using a name at all. – Greg Hewgill Jul 14 '12 at 05:50
  • A string literal is a read-only object of type char-array with static storage duration. How a compiler implement this read-only property (as/in "constant data section","read-only data segment", or whatever...) is ever implementation-defined and therefore not primary. – user411313 Jul 14 '12 at 17:13
1

If you are referring to the location where the string OK is stored, then its stored in the code section of the memory and ptr is stored in the stack.

And the location of OK in code section is still accessible as its address is being returned by func().

Also, the code section is read only. That is the reason why other answers suggested to make your function declaration as:

const char * func ()

That ensures the value pointed to, by returned address to be not modifiable. (pointer to a constant)

tonyjosi
  • 717
  • 1
  • 9
  • 17
0

ptr holds the address of the "OK" data in the constant data section. That is the address being returned. Not the address of ptr So even if ptr ceases to exist, "OK" continues to remain

Andy Stow Away
  • 649
  • 1
  • 8
  • 17
0

char *ptr = "OK"; - This statement will allocate 4 bytes(if it is 32 bit machine) for the variable ptr and it will hold the address of the string literal OK. Now ptr is having a starting address(4bytes) of a string OK (which is actually 3 bytes including \0). This 3 bytes stringOK will be in text segment, which is a read only data. You can't modify also. For example ptr[0] = 'T' is not possible in this case. String literals(3 bytes) in the text segment will exist through out the life time of process. But once the control comes out of the function func, then 4 bytes allocated for the variable ptr to hold address of the string literal will be freed. You can write your function func like below also

char* func()
{
    return "OK";
}

Change your function like below

char* func()
{
    char ptr[] = "OK";
    return ptr;
}

This time 3 bytes will be alloacted for the variable ptr to store the string locally. Scope of this is within the function only.

rashok
  • 12,790
  • 16
  • 88
  • 100
0

ptr itself on stack is transient but where it points to is not. One circumstance is like in your func(), which string literal is stored in "constant data area", the other circumstance is data being allocated on the heap, i.e. through malloc(), therefore being global and would not be destroyed when the stack of function is gone.

char* func()
{
        char* ptr;
        ptr = (char*)malloc(100);
        strcpy(ptr, "OK");
        return ptr;
}
Xu Hong
  • 849
  • 2
  • 7
  • 10