In this lesson we will talk about pointers
as return type for functions. Pointer is just another data type. It's just that a pointer stores the address
of another data type. So it is quite possible for a function to
return pointer. But we must understand the use cases in which
we may want to return a pointer from a function. So let us try to understand this. I'll get started by writing some code. Now I want to write a very simple C program
initially. I want to write a function Add that will take
two integers as argument and sum these two numbers and return the sum. So let's say we declare another variable c
and c equals a + b and the function returns c. Now in the main method I'll initialize two
variables. Let's name these variables x and y. Let's say x is equal to 2 and y is equal to
4 and we will have another variable z which will be the return of this function Add and
we will pass x and y as arguments to this function. Finally, I'll print something like sum is
equal to z. No prizes for guessing the output here. Now I'll modify this code slightly, but before
that I want to talk about this concept once again that x, y and z are local variables
to main function and a, b, and c are local to Add function. What really happens when we call the Add function
is that value in this variable x of main is copied to variable a of Add. And value in y of main is copied to b of add. And what if we name these variables in main
a, b and c instead of x, y and z. If we run this code, output will be the same. This time what we will say is that the value
of a in main is copied to a of Add and the value of b in main is copied to b of Add. This a in main and this a in Add - they're
not the same. You can verify this by printing something
like this. I'm printing the addresses of these two 'a's
in my code and as you can see address of a in main is something like 2883032 and in Add
it is 2882792. So they're not the same. That means these variables are not the same. They're at different memory addresses. The names of variables are local or specific
to a particular function. In our example here, the method or the function
main can be called "calling" function and the function Add can be called "called" function
in this particular call, when we're saying that c is equal to Add and passing a and b. And this call where a and b in main are getting
copied to a and b in add, this is called a call by value. Now what I want do is, instead of passing
by value I want to pass the addresses of these two variables. So I want to say that I want to pass the address
of a and address of b to the Add function. So the signature of Add function should be
such that it should receive the addresses. So I'll say that, okay, it takes 2 pointers
to integers a and b. And now we can access the values at these
addresses by using this asterisk operator which is used to de-reference an address. Now such a call is called call by reference. a and b are integers local to main function
and in the function Add, a and b are not integer variables. a and b are pointer variables, pointer to
integers. So their type is different. They're not int, they're int* But at the end
of the day, they're also variables which are local to the function add. It's just that they're not integers. And now I'm using these two variables which
are pointer to integers to access these two variables a and b which are in the main method. And to do so we use the asterisk operator
and now, this code should also work. I'll write a few more print statements inside
this function Add. I have tried to print a and I have tried to
print *a and initially I was printing &a. So now &a should give us the address of the
pointer variable. a should gives us the address of a in main
because that is what this variable stores and *a should give us the value of a in main. Let us see in the output. Now as you can see here, the address of a
in main is 3537612 and address of a in Add is something else, but the value of a in Add
which is the address of a of main is equal to 3537612. So the first and the third lines are same
And using the address, we're printing the value which is equal to 2. Now I'll clean up some of these print statements. Coming back to our function add, we're returning
this value c. And once again in the main method, we're collecting
this value c in another variable which is c of main. Now why not do something like pass the address
of this c in Add function. So what we will do now is we will say that
we want to return pointer to integer from this function and here we will return &c. Now & when it is put in front of a variable
it gives us the address. Now of course, here we will have to collect
this particular address, so we will have to define a pointer variable. Now this would be ok. Now when we're printing, we will have to print
the value at address being pointed to by this variable. Now what we just did is we modified this Add
function to return a pointer to integer. There are two syntax-es We can say int and
then put this * sign or we can say int and put the * sign in front of the function name
Add and both these syntax-es are valid. Now this function is returning pointer to
integer. Let us run this program and see what happens. Let me also strike off this print statement
here. Okay, so the output seems to be alright. Now have you caught some logical error with
this code already? If you haven't stay with me for sometime. Now what I want to do is I want to write another
function, a simple function that will print "hello world". So I'll name this function PrintHelloWorld
and in this function I'll write a simple print statement. Now before I print this sum, what I'll do
is I'll call this function PrintHelloWorld() And let's see what happens now. Oops - this looks weird! Sum is not correct now. I just saw that it was coming fine in my last
run when I did not call this PrintHelloWorld. What happened? So let's try to understand what really happened
here? I'll come back to this familiar diagram of
various sections of application's memory. The memory that is allocated to a program
is typically divided into these sections. All the local variables and the information
about function call executions goes into the stack. So let us run through this code, let us simulate
this code and see what's really happening in the memory. For each function call, some part of memory
from the stack is allocated for its execution. Now we call this the stack frame of that method
or that function. When the program starts executing, first the
main method is invoked. So in the stack frame the memory will be allocated
for the main function and all the local variables of the main function will live inside this
stack frame. Let's say the starting address of this stack
frame is 100 and the end address of this stack frame is 130. And we will have 3 local variables created
here - a, b and ptr. a and b are integers and ptr is an integer pointer. Let's say a is at address 100 and b is at
address 112 and ptr is at address 120. I am just making these assumptions. Now when the main method will come at this
line where it is calling Add function, its execution will pause and now memory will be
allocated for the execution of Add. At any time whatever function is at the top
of the stack is executing. main method will wait for Add function to
complete and return. Here I should say a is equal to 2, b is equal
to 4 and now Add comes here in the stack. Let's say Add gets memory from 130 to 160.and
Add also has 3 local variables - a, b and c. a and b are pointers to integers. The value of a will be 100 and the value of
b will be 112. Let's say their addresses are 130, 140 and
144. Once again these are just random assumptions. Now c is calculated as *a + *b. a is pointing
to this location and b is pointing to this location. *a is value at address stored in a and *b
is value at address stored in b. So this c will be 6 here. These two values will be added. Now this add function will return the address
of its local variable c which is 144 and finish its execution. So this ptr will be 144 and now the memory
that is allocated to Add function will be de-allocated. Now this memory above address 130 can be used
for other function calls. And even though this variable ptr stores the
address 144, the address of this particular block (it kind of points to this particular
block), the date here is not guaranteed because this memory has been de-allocated. Now we come here to this PrintHelloWorld and
now memory from stack will be allocated to PrintHelloWorld above this stack frame of
main method. This is main. So let's say that PrintHelloWorld gets this
memory block from address 130 to address 150. Now there is no local variable in this PrintHelloWorld
function. But still, function call execution involves
storage of some information. Now this section, from 130 to 150 is for PrintHelloWorld. I'll write PHW - shortcut for PrintHelloWorld. And it has been over-written. So this block at 144 no more stores value
6. So when we come here at this print statement,
to print the value at this particular address, we get some garbage value. Now the obvious question would be, why did
we get the right value when we were not making the call to PrintHelloWorld. I would say that I just got lucky. Maybe because I did not call any other function
after making a call to Add, my machine did not overwrite or erase the data at that particular
memory location. But when I made a call to PrintHelloWorld
that memory got used. If you see, we have passed the addresses of
these two variables a and b of main to Add function. But that is alright because called function
always comes above the calling function in the stack. So any time this called function is executing,
calling function will be in the memory. So if Add is executing, main is guaranteed
to be in the memory. So addresses of variables in main will be
accessible to Add. But if we try to return a local variable from
the called functionback to the calling function - like if we want to return a local variable
from Add to main, when that function finishes and the control returns back to the calling
function that memory has already been de-allocated. So it is ok to pass something from bottom
to top in this call stack, or I should rather say that it is ok to pass a local variable
or address of a local variable from bottom to top in the stack but it is not ok to return
the address of a local variable from top to bottom in the call-stack. I hope this makes sense. So now the obvious question would be - what
are the uses cases in which we may want to return pointers from functions. Well, if we have address of some memory block
in the heap section or some memory block in the global section, then we can safely return
the address of these blocks because anything in the heap has to be explicitly de-allocated. We control its de-allocation unlike stack. And anything which is in the global section,
a global variable, lives for the entire lifetime of the program. I can use malloc or new operator in C++ to
get some memory on heap. So if I modify my code something like this,
I will declare this c as a pointer to integer and get some space allocated on the heap using
a call to malloc. malloc is a library function that returns
pointer, but it returns pointer to an address which is on the heap. So we get a memory block and using this pointer
variable now, we can write this value - *a + *b - at that particular memory block. And then we can return this address c, which
is the same address that malloc returned us but we are safe now because we are returning
address of a block which is on the heap and not on the stack. And this will work now. Now in this code, let's say this call to malloc
gives us this block at address 500 in the heap. c now is only pointing to this block and using
c we have written this data here, this value 6. And now when add finishes, the address returned
by the Add function which is address 500 is still valid. We still have the data there and it will not
be de-allocated. Anything on the heap has to be explicitly
de-allocated. So while returning pointers from functions,
we need to be careful about the scope. We must be sure that the address is not re-used
to store something else or that the data is not cleared from that address. In most cases we will be returning pointers
to memory that is allocated on the heap, or memory that is in the global section, the
global variables section. In our coming lessons, one place where we
will be using pointers as function returns in our code is implementation of linked list
data structure. So this was pointers as function returns. Thanks for watching.