 Hello and welcome back. This is the second part of our two part lectures on structures and pointers. Here is a quick recap of some of the relevant topics we have already studied. We have studied about structures as collections of variables or arrays or other structures. We have seen how statically declared structures can be used in functions. We have studied about pointers to structures and we have also seen how members of structures can be accessed directly or through pointers. In this lecture, we are going to study how we can have pointers themselves as members of structures. This will naturally lead to the notion of linked structures which we will study and we will also study about dynamic allocation and deallocation of structures. Some examples in this lecture are from the book, An Introduction to Programming through C++ by Abhiram G. Ranade published by McGraw-Hell Education in 2014. All such examples will be indicated in slides with the citation AGR book. Let us quickly recall how memory for a program in execution or a running process looks like. Well, the operating system is going to allocate a part of the main memory for use by the process and this part in turn is going to be divided into three segments, the code segment for storing executable instructions, the data segment for dynamically allocated memory and the stack segment for storing the call stack. Let us see how this memory layout might look like for a simple program like this. Now, this program is actually part of a taxi queuing system. We will see the complete program for the taxi queuing system in a later lecture and this taxi queuing system problem is actually inspired by an example in AGR book. So, here I have shown a skeleton of the main function of the taxi queuing system program where two structures have been defined. The structure driver has a member name which is basically a character array of size 50 and it also has a member ID which is of type integer. The structure taxi has a member ID of type integer and it has a member DRV which is a pointer to the structure type driver. So, the type of the member here is a pointer to a driver. Now, if we assume that every location in main memory in our computer can be addressed using 32 bits of address, then every pointer which must store such an address really would require 32 bits of storage or 4 bytes of storage. Now, we have also defined two variables here D1 and T1. D1 is a variable of structure type driver and this is a local variable of main. So, space for it is going to be allocated in the stack segment and in this space there will be space for the member name and there will be space for the member ID. The sizes of these two rectangles here are not drawn in proportion. We will consider that this space is adequate to store 50 bytes for the character array of size 50 and this space is adequate for storing 4 bytes for the integer member ID. Similarly, the variable T1 will have space for it allocated in the stack segment because it is a local variable of main and in this space there will be space for the member ID and there will also be space for the member DRV. Note that DRV being a pointer we need only 4 bytes for storing the value of DRV. So, the space required for storing the value of DRV is the same as the space required for storing the value of ID. This is an integer, the other is a pointer. So, now if I have this assignment statement D1 is assigned shaker comma 23 then in the space allocated for the member named name of the variable D1 the string shaker will be copied and similarly 23 will be copied in the space allocated for the member named ID of the variable D1. Subsequently, if I say T1.ID is assigned 12 then in the space allocated for the member ID of the variable T1 12 will be copied and then if I have this assignment statement which says T1.DRV is assigned ampersand D1 then I will first calculate the address of the variable D1. If you recall D1 was basically stored in this sequence of memory locations. So, when I am asking for the address of D1 I am basically asking for the address of the first in the sequence of locations. Let us say that address in hexadecimal notation is 230 then in the space allocated for DRV for the variable D1 for the variable T1 the hexadecimal value 230 will be stored. If you look at this memory layout you will realize that the member DRV of the variable T1 actually has the address of the variable D1. So, basically this member is pointing to this variable such a relation where a member of one variable of one object points to another variable or object can also be very conveniently pictorially represented in this manner. We simply draw an arrow from the member of the first object to the second object that it is pointing to and we informally say that T1 is linked to D1 through the member DRV. Now that we have seen how two objects in main memory can be linked one might want to ask that can we link the taxi structures that we have seen earlier. Basically we want to have a taxi in the queue also have information about the next taxi in the queue. So, can we link these taxi structures? Well in order to have a taxi have information about the next taxi in the queue can we use a structure like this where now the structure name is link taxi and it has the usual members ID and DRV as before and it also has a member next which is of the same structure type link taxi. Now we have seen in an earlier lecture that such a structure definition cannot be allowed in C++ because this would otherwise lead to objects of the structure type link taxi requiring infinite amount of storage. Well what can we do? Can we try the following alternative? So instead of having next being of type link taxi can I have next being a pointer to link taxi and in this case does an object of structure type link taxi still require infinite storage? Well it is easy to see that it will not require infinite storage because this member is merely a pointer to another object of structure type link taxi and a pointer just requires 4 bytes of storage and therefore the total amount of storage required for this structure is finite. So now that we know how the link taxi structure might look like let us see how we are going to represent linked structures in main memory for a simple program that we are going to show here. So here we have the structure driver we have seen before we have the structure link taxi that we have seen before and there are these 2 variables D1 and D2. So of course space for these will be allocated in the stack segment since they are local variables of main and as before the space for each variable will have space for each of its members. Similarly T1 and T2 are variables of structure type taxi so these being local variables of the function main space for them will be allocated in the stack segment and the space for each variable will have space for each of the members of the corresponding structure type. So here the space for T1 will have space for ID will have space for DRV which is basically a pointer and will also have space for next which is also a pointer. Now suppose I execute this assignment statement D1 is assigned shaker 23 then in the space allocated for D1 the string shaker will be copied in the space for member name for the member named name and 23 will be copied in the space allocated for the member named ID. This assignment statement D2 is assigned Abdul comma 34 will result in a similar copying of the strings Abdul and 34 in the spaces allocated for the respective members of the variable D2. Now suppose I execute this assignment statement T1.ID is assigned 12 so in the space allocated for member ID of the variable T1 12 is copied T1.DRV is assigned the address of D1 so T1.DRV is now going to point to D1 and T1.NEXT is null null is of course the 0 pointer so in the space allocated for next in the variable T1 the all 0 value is stored. What about the next sequence of assignment statements T2.ID is assigned 11 so 11 is copied here T2.DRV is assigned the address of D2 so T2.DRV starts pointing to the variable D2 and T2.NEXT is assigned the address of T1 so the member next of the variable T2 now starts pointing to the variable T1. So you see that here I have T1 and T2 both of which are variables of the same type and a member of T2 named next is actually pointing to T1. So this is how a linked structure can be created in main memory and now if we execute this output statement what will get printed well we will first access T2.NEXT that is a pointer. So now we will have to see what object that pointer points to and we will have to access the DRV field of that object that also happens to be a pointer. So because of this arrow operator we will have to go to the object that that pointer points to and we have to access the name field of that object and there we get the string shaker and therefore the output of this program is going to be shaker. Well let us also see how dynamic memory allocation and deallocation can be done with structures. Recall that we had used the new and delete commands for dynamically allocating and deallocating memory for variables and arrays of basic data types. So here is a simple example to refresh your memory. My pointer is a variable of type integer pointer. This is a local variable in a function. So space for it is allocated in the stack segment and when I execute new int space for one integer is dynamically allocated in the data segment or heap and a pointer to that is returned by new. So this assignment statement will copy that pointer to my pointer and therefore my pointer will now start pointing to that space allocated by new in the heap. The second assignment statement will allocate space for three integers in the data segment or heap and it will return a pointer to the first location of the space allocated for these three integers and that will get copied to my array. My array is of course a local variable of the function. It has its space allocated in the stack segment and so now my array will start pointing to the first of these three integers allocated in the data segment or heap. And of course when we do delete then the space in the heap that was pointed to by my pointer. When I do delete my pointer whatever locations in the heap my pointer was pointing to is freed. Similarly when I do delete as an array my array whatever location in the heap as an array that my array was pointing to. So my array was basically pointing to some locations in the heap as an array and those entire set of locations are going to be freed when I say delete as an array the locations pointed to by my array. Now exactly the same thing is going to happen if I use new and delete with structures. So for example, here is our favorite driver structure and here I have my driver pointer which is a local variable in a function space for it is allocated in the stack segment when I say new driver space for an object of the structure type driver is allocated in the data segment or heap. So of course, this space will have space for the member name, it will have space for the member id and a pointer to this space allocated in the heap will be returned by new and that pointer will be assigned to my drv pointer. So my drv pointer will basically be pointing to that space for an object of type driver allocated on the heap. Similarly when I execute this statement space for two objects of type driver allocated on the heap and the address of the first of these objects is returned and stored in my drv array. So my drv array points to the first of these two array elements allocated on the heap. And of course, when I say delete my drv pointer the entire space for the object of type struct driver that was being pointed to by my drv pointer the entire space for that object that was allocated on the heap will be released and similarly when I say delete as an array my drv array then the entire space in the data segment or heap that my drv array was pointing to when viewing that space in the heap as an array of structure type driver that entire space is going to be released. So this statement basically asks us to release the entire space in the heap that my drv array is pointing to where that space in the heap is going to be treated as an array of object type driver. So there are some caveats when you use new and delete these caveats are really the same as we have studied earlier you must not assume that new always succeeds you can indeed fail and return null. So you must always check after new whether the pointer returned is not null before you dereference the pointer as is shown in this example here. Similarly when using delete you must not try to delete a null pointer. So you must always check whether the pointer is not null before calling delete on that pointer variable. So in summary in this lecture we looked at members of pointer data types within structures we looked at linked structures and we also saw how structures can be dynamically allocated and deallocated in the heap. Thank you.