 So, in this lecture we are going to see how pointers are used in C++ programs. So, I am not going to spend too much time on it, I believe all of you have already gone through this. So, there is no point doing that, we are not keeping track of that. So, here is a simple program which is there in the slides has integer variables pointed to integers and pointed to pointed to integers and did anybody have any problem going through. So, of course, in the video lectures we have explained in great detail what exactly happens is each statement is executed, but did anybody have a problem going through this program? No, if not then we will just you know skip it because this is actually completely straightforward. I mean there is a pointer in which once takes the value of n another time takes the value of m and pointer pointer int always points to pointer int. So, in this case star pointer pointer int is pointing to pointer int and pointer int is pointing to n and in the other case pointer pointer int is pointing to pointer int and pointer int is pointing to m and so the values of n and m are printed out. So, we will just skip this because this is fairly straightforward if you understood what ampersand and pointers are about. The point I want to sort of bring to your attention is that when we use star pointer it is not that we can just read the contents of the memory at the specified location, we can also write the contents of memory at that location. So, here is the expression b plus c whose value is being stored in the memory location whose address is pointer int and then here is another program which also does something fairly straightforward. So, there is this integer variable called sum and the address of that is stored in pointer sum and then pointer int once stores the address of n and another time stores the address of m and here so this statement star pointer sum plus equal to star pointer int is basically this we have already seen what plus equals mean long back. So, in this case I am going to access the value of star pointer sum which is 0 and star pointer int which is the value of n and add them and store them in the memory location whose address is given by pointer sum and the next time around I am going to do the same thing, but this time of course pointer int is pointing to m. So, basically the values of m and n are added and that is what gets printed out when that statement is executed. So, did anybody have a problem understanding this in the video lecture? So, let us go to the next one. So, this is about pointers and functions. So, basically we have studied functions before Midsum itself and when we talk about functions we can talk about passing parameters either by value or by reference and we also know that whenever a function is called an activation record for that function is created what goes in the activation record all the local variables space for all the local variables the return program counter the return value of the program counter and some other bookkeeping information and this entire activation record is pushed into the call stack and the call stack resides in the stack segment. So, the question is can we pass pointers as function parameters and can we return pointers from functions? Now, if pointers are legitimate types I mean I am defining variables of type pointers. So, if pointers are legitimate types then it should be possible to pass arguments of pointer type to a function and also for a function to return something of pointer type. So, here is a simple one which is swapped by pointer. So, here I want to swap the values of m and n which are two integer variables in main and if I write swap in which I pass the values of m and n by value then we have seen earlier before Midsum that what is going to happen is inside swap the local copies of m and n will have their values swapped, but when the function returns main will not be able to see the values swapped. So, here is one way of actually letting this function the called function access local variables of the calling function. So, actually pass the pointers ampersand n and ampersand n will give you the addresses of m and n. So, you pass these pointers to the called function and then the called function then manipulates the memory at those addresses using the star operator this is fairly straight forward and that is what is basically illustrated here. So, this is the activation record of main which has m and n and there are two addresses corresponding to m and n. And this is the activation record of swap by pointer and when I am passing the addresses of m and n what is getting copied in the you know these are the spaces allocated for the formal parameters of swap by pointers. So, what is getting copied there are the addresses of m and n and now that swap by pointer has the addresses of two local variables in the activation record of main it can actually use the star operator to go and access those variables read their values change their values whatever and then that is what exactly happens and that is how the values of m and n are changed in the activation record of main by the function swap by pointer by different function right. And if you recall we were able to do something like this earlier by using parameter passing by reference here we are passing parameters. So, what is this this is passing parameters by what is it by value or by reference? How many of you think it is reference value and there are some undecided yet. So, for those of you who are undecided this ampersand m is an expression we talked about last time. So, this is an expression which evaluates to a pointer type this is an expression which evaluates to a pointer type and this is a function call where the two expressions values are being passed using call by value. So, the called function which in this case is swap by pointer is going to get two values copied the address of m and the address of n copied from the main function here. So, this is really called by value I have found out the addresses of m and n and I have copied those values here in the formal parameters for swap. The point that I was saying is that passing parameters by reference also accomplishes this and it is interesting that when you actually write a function call where you pass parameters by reference behind the scenes the compiler is actually using something like what we just saw it is actually passing pointers to those variables. So, that the called function has access to the local variables of the calling function. However, passing parameters by reference is not exactly the same as passing parameters pointers call by value through pointers and there are some subtle differences we will not get into those, but here is a quick sort of comparison of how the two things might look like. So, here is the main function and here we have written two functions swap by pointer and swap by reference they are both doing the same thing swapping the values of the two arguments passed as parameters. In this case I am calculating the addresses of m and n passing them using call by value and then using the star operator to directly access the variables m and n over here and in this case I am calling them directly as m and n, but when I write the function here I say that these are parameters called by reference. So, note the difference when I am calling by reference I do not do anything where it is called, but in the function definition I indicate that these are called by reference. When I am passing pointers I calculate the pointers here and in the function I say that these are pointer valued parameters which are being copied by value. So, of course, you could pass pointer valued parameters by reference also. So, both of these functions do the same thing, but I guess this is a slightly cleaner way of doing it here you do not need to keep saying star, star, star all over you just need to say right here when you are declaring the parameters that these are parameters by reference. It is also cleaner when you call it here you do not need to compute the addresses. So, that is why pointer parameter passing by reference is preferred most of the times that parameter passing by pointer values. However, you can use both. Can a function return a pointer? So, if pointer is a legitimate type then certainly it can, but you need to be careful about what pointer value you are returning. So, for example, here is a function which is a local variable a and it is returning the address of that local variable a right. So, this local variable is going to reside in the activation record of this function in the stack segment. So, as long as this function call is active that activation record is there and the variable a has a legitimate address and you can talk about ampersand a being a legitimate address, but the moment this function call returns that activation record is gone it is popped out of the call stack. So, the space allocated for a is also now freed up it no longer necessarily belongs to a the operating system is free to allocate to somebody else if it wants. From the same program somebody else might require that space. So, after the function call returns the address of the variable a is really the address of something that had some meaning earlier, but no longer has a meaning once the function has returned right. So, when you try to dereference that address here as star a right. So, this is whatever my funk is being called with some integer pointer and it is returning some pointer value which is the address of this local variable. And when you are trying to dereference that over here you will have a problem because you are really dereferencing a bad address. What does it mean that it is an address which had some meaning the those locations had some meaning when the function was called when the function was active, but when the function is returned that entire activation record has been freed up. So, those locations do not necessarily have the same meaning at that they had when the function was active and the function call was active. So, there could be something else stored here and so if you write star a it is going to print out something, but it could be garbage it may not be what the value of the local variable here was. However, you know here is an alternative function where what it is doing is it is taking an integer pointer and it is actually passing returning that same integer pointer back. It is doing some calculation in between it is whatever calculating the square of the integer over there storing it there and it is returning that same integer pointer back. So, if you look at it, I have passed an integer pointer here which is actually the address of a local variable in main. Now, my funk is going to basically square the value of b store it back in b and again it is going to return the same pointer that was passed to it. Point of b was passed to it it is going to return that same pointer. So, the address of b was passed to it. So, it will return the address of b. So, a now contains the address of b and b is a local variable of main. So, when I do star a, I will actually get the value of b, but it is the value of b after some updates have happened over here. So, this is a legitimacy referencing. Is that clear? So, that is all that we had in this lecture, are there any doubts about this? So, let us start the quiz. So, that is the first question. Consider the following function call int a, b's you are reading in the values of a and b and then you are calling a function using ampersand a and ampersand b. So, we have just discussed this. So, parameters are being passed here by which mechanism? If a function f 1 calls a function f 2 which of the following are possible f 2 can change the values of local variables of f 1, f 2 cannot change the values of local variables of f 1, f 1 can change the values of local variables of f 2 other than the formal parameters of f 2. The formal parameters of f 2 are also local variables of f 2. So, this says that f 1 can change values of local variables of f 2 other than the formal parameters of f 2 and none of the above. Which of the following are true of function calls in C plus plus? Can accept pointers as parameters can return a pointer cannot dereference it should not be difference cannot dereference pointers fastest parameters and cannot return a pointer if pointers are past as parameters. So, swap function that swaps the values of two integer variables in the calling function can be implemented by passing parameters by reference value when the value could be value of a pointer both a and b and none of the above. And a function f 1 returns a pointer to a local variable of f 1. If f 2 calls f 1 and tries to dereference the pointer returned by f 1 which of the following may happen memory access error during runtime no error during runtime reading of garbage value by f 2 and none of the above. Okay, so now we will start our practice questions. So, let us see we have 45 minutes let us be a bit ambitious and try to attempt three practice questions. So, here is a code snippet what I would request all of you is to write down this in your notebook because there is another part of the code snippet on the next slide. So, please write this down this is a function which takes an integer pointer and an integer and then it does some things and here you see that it also calls itself recursively. So, now we want to invoke this function from the main function in the following way. So, in the main function we want to have an integer pointer variable p and there is an integer variable q which has to be initialized to something and then we want to call that function fun that you just saw in this manner and we want to print out the value of star p. So, the question is what value of this question mark will cause dereferencing of a bad address when trying to print star p and what value of question mark will avoid this problem and what is the value output in that case. When you are dereferencing a bad address there is no guarantee on what value you will be outputting but when you are not dereferencing a bad address then you should be able to say what value you are putting out. Please try it on by yourself first write down in your notebook and then after a few minutes we will ask you to swap your notebooks and then we will have a discussion. So, I have a sample answer here. So, what he is saying is that if you put q is 0 if you initialize the value of q with 0. So, then what is going to happen is you will get ampersand q and q is initialized to 0 and 0 these are the two arguments and here star of ampersand q will be just the value of q and b is already 0. So, 0 equals 0. So, it will return a which is the address of q. So, p will get the address of q and then when you try to dereference p you are fine because q is already a local variable in the main function. However, if it is something other than 0 int q is any value other than 0 something. Yeah. So, I guess what he is trying to say is that if you use a value other than 0 over here. So, what exactly is going to happen? So, suppose I say q is 5 over here. So, this will be ampersand q and 0. So, here I have the address of q and here I have 0 and star of the address of q will give me the value of q which is let us say 5 something other than 0 and that is not equal to 0. So, it will go into the else part. And in the else part what will it return? It will make a recursive call to funk ampersand cc. C is a local variable of this function. So, what is that going to return? So, it will enter this function again and now it will try to do star of ampersand c. So, it will get the value of c which is 0 and this c is also 0. So, does everybody see that when this call is made the recursion will stop because c already has the value 0. So, when I make that recursive call with the address of c and then when I take star of that address, I will actually get the value of 0 here and this is also 0. So, this condition will get satisfied and so, it will just return the address of c. So, what happens is you make a call which is let us say funk of ampersand q and 5. So, p is assigned this and inside funk what happens is you are trying to check if star of ampersand q is equal to 5 then you return ampersand q. This ampersand q is the first parameter of funk. Else you return funk of ampersand c and c where c was initialized to 0 as a local variable. So, what does this call do? This call itself you know another call here. So, it also sets its own copy of the local variable c to 0 and then it says if star of ampersand c is equal to 0. Remember the value of c here that was passed was the value of c which is 0 and this is the address of c from the activation record of the first call to funk. So, we are asking if star of ampersand of c is equal to 0 and indeed the value of c in the activation record of the first function call is 0. So, it will return ampersand c. So, since this is indeed equal to 0. So, it will return ampersand c. So, this function will return the address of c in the first call to funk. This is the second call to funk which will return the address of c in the activation record of the first call to funk and therefore from here it will return that same address back here. Is that clear? So, the second call to funk returns the address of c in the activation record of the first call to funk and when it returns that that value is returned directly back to the main function. So, here what I get is the address of c in this first in the activation record of the first call to funk. But by the time I return here the activation record of the first call to funk is gone. So, therefore, p will get assigned the address of a non-existent variable and so when you try to dereference it you will be dereferencing a bad address. Is this clear to everybody? This is the first call to funk. This is the second call to funk. First call and this is the second call. The value returned from the second call to funk is actually a legitimate address inside the first funk call because it is the address of a local variable in the activation record of the first call to funk. But the value returned by the first call to funk is not a legitimate address in main because it is the address of a variable in the activation record of the first call to funk which is gone by the time the first call to funk returns. Are there any doubts about this? And this is a very simple example of how pointers can be shipped back and forth across functions. So, let us look at the second question we are doing with respect to time. So, the second question actually builds upon what we had already seen in the last class. So, in the last class we used one-dimensional arrays to store data in such a way that we could access the data as a two-dimensional array. For example, in order to access a 10 by 10 array of int, actually Govind showed us last time that we could actually do this. Actually, several of you also came up with this solution independently. So, we could, so to access a 10 by 10 array of int we used 10 one-dimensional integer arrays and then we used one one-dimensional integer pointer array in which we initialized them with the address of the first element. Instead of writing ampersand a10, you could also write a1 which will also give you the address of the first element in a1, but this is being very explicit saying take the first element in a1, find its address. Of course, these dot dot dots are not legitimate in C++. You have to write a310, a410 and so on. I have just written this here to save space. This is what we did in last class. This is what Govind showed us in last class. So, now what we want to do is, we want to write a function, call that function get2d array and it will take two parameters, two integer parameters n1 and n2 and it will return a pointer to a pointer to an integer. And what we want, how we want to use this function is, I mean this is a sort of example usage of this function. So, I am saying get2d array 10, 10. So, this should give me back something which I can use as a 10 by 10 two-dimensional array. So, for example, I could have these two nested for loops and I could do something like this. So, recall that last time also we had said that we should be able to access the array like this. That is what we are insisting this time also. But now we want this function which should take these as parameters and it should return us back something which we can then use over here. Is that clear? So, it is really the same thing, but now you realize that it is going to be a bit different, I mean not too much different, but bit different from what Govind had shown because there he knew that it was a 10 by 10 array. So, he could declare 10 such arrays, but here I might say 10, 10 now and I might say 100, 100 next time or I might say 30, 10 the third time. So, I cannot pre-define a certain number of arrays. Here since we knew this was a 10, 10, we pre-defined 10 arrays each of size 10, but here this is somewhat inside the parameter. Now, you may assume when you are writing this function get 2D array, you may assume that you have access to the following black box functions. What do we mean by black box functions? These are functions like you know coming from a library. So, you can use them, you know their contract behavior, but you do not care or you do not know about how they are implemented. So, what are these two black box functions? One is a get one dimensional integer array int n and the other is get one dimensional integer pointer array int n. So, each of these functions may be assumed to return a pointer to an array that can be accessed even after the function returns. Now, from whatever we have learned so far, this I mean this looks like something that is that requires something beyond whatever we have learned so far that I will call this function until return me an array and then I can access that array even after that function returns after its activation record is gone. But let us assume for the time being that we have some such functions. So, let us just for the time being assume that you have these two functions given to you when you call this function with 5 over here it returns you an integer pointer which you can use as the address of the starting element of an integer array of size n whatever that n is and similarly when whenever you call this function it returns you an array of integer pointers and the size of that array of integer pointers is n whatever the parameter you pass to that. So, is this clear? So, I want you to write this function such that I can use it in the main function like this and in writing this function you are allowed to use these two functions in whatever ways you want without worrying about how those functions are implemented. We will see we will look at their implementations in the next class itself. So, you know when you write c out less than less than n do you ask how does c out work? So, I am saying what that function will do? Of course, that is written here it returns a pointer to an array of course, this is returning a pointer to an array of integers this is returning a pointer to an array of integer pointers that can be accessed even after the function returns. So, for example, suppose I call this function and I assign the return value of this function to a. So, if I write a assign get 1 d int array 100 then after that statement I can write a 5 is assigned 3 whatever it has returned is now an integer array of size 100. Similarly, this one is an integer pointer array of size whatever. So, once you call this and it returns something and you copy the return value somewhere you can use that thing now as an array of integers or integer pointers of whatever size you have specified. So, I am not sure if we can go into the third problem, but there was really nothing much difficult about this problem. So, let me show solution go in the game. So, here was last time solution. We had asked you to build a 10 by 10 array and so what we did is we went and declared 10 arrays each of size 10 and we filled up and each of these was an integer array. So, we basically needed some integer arrays and we needed an integer pointer array. So, these two functions are exactly for that to get the integer arrays and to get the integer pointer array. Here we had statically or while writing the program itself we had declared all of these 10 integer arrays and how did we know that we had to use 10 integer arrays because it was a 10 by 10 array we were trying to use and the size of each of this 10 integer arrays was 10 because we knew that this was going to be a 10 by 10 array. So, now in our case we want an n1 by n2 array. So, how would you do an n1 by n2 array using the same idea perhaps you would have n1 arrays each of size n2. So, if I could declare n1 arrays each of size n2 and then I could put all of those n1 arrays the address of the starting element of all of those n1 arrays into this array of size n2, but it is now an array of integer pointers then we would be done. An n1 by n2 array is basically n1 arrays of size n2 and then put the address of the starting element of each of those n1 arrays into another array which is an array of integer pointers as of size n1. So, that is exactly what we are going to do and that is all that is there. So, I mean if you understood this solution there is really nothing much here. So, he is getting the one-dimensional integer pointer array. So, we said n1 by n2 means n1 arrays of size n2 and then the address of the starting element of each of these n1 arrays will be stored in the resulting array which will be an integer pointer array. So, that is what he is doing here. He is having this integer pointer array of size n1 which he is calling as a and then each element of that array that he got here should contain an array of size n2 and this should be an integer array of size n2. I mean we are just trying to replicate what we did here. I mean n1 by n2 array means n1 arrays of size n2 each of these arrays is an integer array and we stored the starting address of each one of these into an array of integer pointers. So, the point to remember here you may be let me emphasize this. So, the point to remember here is that when we say there is an integer array of size 5 let us say when we declare an integer array of size 5 a3 is an integer, a0 is an integer these types are integer types, but a itself is of type integer star. In fact, a0 is the same as star of a plus 0, a3 is the same as star of a plus 3 and if you recall the pointer arithmetic business I just told you in the lecture a plus 3 means if a is an integer star a plus 3 means it will actually add 3 times 4 because each integer would require 4 locations. So, it will calculate the address which is given by the value of a plus 3 times how many ever locations are needed to store an integer because a is an integer pointer. So, when we are saying that we are returning an array a we are really returning an integer pointer I mean if a is an integer array. So, if I have an integer pointer array let us say b size 10 then b0, b1 all of these are integer pointers up to b9 these are all integer pointers, but b itself is an integer pointer pointer. So, that b0 is really star of b plus 0, b1 is star of b plus 1 where that plus 1 really means find out the type of what b is pointing to find out how many locations it takes and plus 1 means one more unit of that many locations. So, what is this? This is an integer array of size 5. So, therefore what should be this this is an integer pointer array of size 10 I mean whatever I write here if I had written char here it would become a character array of size 6 whatever. So, this is a type. So, int star is a type. So, this is saying this is an array of this much size each element of that array is an integer. So, this is an array of this much size each element in that array is an integer pointer. So, this is an array of integer pointers right I mean this is the general format for declaring any array you provide the type you give the array name and then you give the size right. So, for example, if I write int star star star b 10. So, this is an array of 10 elements and each element is of type int star star star if I write it like this that is what I mean that is what it means in C plus plus. So, therefore each element in this array is going to be of type int star star star if I have declared it like this. So, here each element of the array b will be of type int star. So, b 0 through b 9 are of type int star and b will be a pointer to that type because as I said b 0 is really star of b plus 0. So, the type of this is obtained by dereferencing b the value of this is obtained by dereferencing b. So, therefore, b should be a pointer to whatever the type of b 0 is if the type of b 0 is int star then b type should be a pointer to int star which is int star star is that clear. So, here in this case the type of b will be int with four stars star of b will have this type because star of b plus 0 which is the same as star of b is really b 0 star of b plus 0 which is the same as star of b is the same as b 0. So, if this thing is of type int star star star then b must be a pointer to int star star star because star of b is int star star star. So, b must be the address of something which is an int star star star and therefore, b must be of int star star star star. So, I guess we have already overshot the time.