 What we will do is, I will ask each one of you to write down three questions that occur to you related to any material that we have discussed so far. I will give you five minutes to write three questions. As a matter of fact, I ask you to put that quiz slip back in your pockets or bags. Please re-select them. There is a different type of quiz. Think for five minutes from the beginning. Let me recap. Now I am recapping the whole course. We looked at the basic introduction to computers, which was straightforward. We looked at the basics of C++, how to declare variables, what are the different data types, what are basic expressions. We looked at the assignment operation. Then we started the journey on more important construct of C++, the iterative solutions and the conditional execution, which formed the crux of our tools through which we can solve larger problems. We looked at functions, how the functions are defined and used. We looked rather deliberately at some details on how function calls are handled and we also looked at recursive functions. Finally, we started looking at another major data structure, which is arrays, of which we have looked at one dimensional array. We have covered a lot of material. So far you have been doing practice problems in the labs, but now onwards you will be actually writing full programs and submitting them. From next week onwards, the marks that will be awarded to you will be on the basis of a full program that you write and submit. A structure would be given, but you will have to write various segments similar to the kind that we look at in our practice problems. And you have to be very exact and you have to upload that file. So as you all know, your quizzes will start at 8.15 and the submission will start at 10 o'clock whenever you finish. That is how we will proceed because now you have to write programs. Because when you do projects, I expect each group to produce at least 3,000 to 5,000 lines of working code which solves a big problem. And these thousands of lines of code will not drop from the Heaven. You only will have to write them. So writing a few lines of code snippets is okay for practice for understanding. But now the honeymoon is over, as they say. Now we come to the brass stats. So in order to do that, I am suggesting a novel format today that based on all the material that we have covered, I will give you 5 minutes to write down 3 questions. And I will ask you to submit these slips because we will analyze these 3 questions. I believe that whatever you ask will be representative of the larger class as well. So we will try to put those things together, categorize them and put their answers next week for all of you to see. So now by this time your background processor must have been working hard to recall what problems you have. Write those questions neatly on the backside. 1, 2, 3. If you are less than 3, it's okay. More than 3, you have to force-order which 3 you think are more important. You may refer to a problem while asking a question. You may refer to a general construct. I'll give you 5 minutes to write 3 questions on all the topics that we have discussed so far. My query was, how many of you have finished writing 3 questions? So far none. My God. To think about the doubts that you have in your mind you are taking so long. You have to order them all. You have so many doubts? No, that's okay. I was just joking. Yes, of course you will have so many doubts. But try to mark the top 3. Let it take 5 more minutes, doesn't matter. It's an important exercise that you are doing. But the more time you spend, the less time we will have for live discussion. We will of course put most of them on to Piazza later. First of all, a big thank you. I have just glanced through many submissions. Some of the questions are very well-framed indeed. It also tells me the plethora of doubts that people have. So if I have to collect each one and sequence them, it looks like I have to redo the entire course. Practically at every place there is some doubt or the other. But that is okay. That can happen. What I am doing is, since there are too many questions and some questions are very well-put, in fact I am just picking out a few questions from the very basics of computing and then proceed as much as I can in the limited time. But we will definitely post all these questions and we will seek answers from you as well, not just offer answers. So here is one question which I have marked. There are some English mistakes, but the person wants to know where does execution of program take place inside the CPU? And there is a related question. So these two questions are related. What is the program counter and where exactly is the program executed inside the machine? So we have talked about the CPU. Let me go back to the architecture and describe what exactly happens inside. You will also know what is the program counter. You are familiar with the memory of the machine. Now so far we were talking about memory locations being allocated to the variables that you define. So each variable gets 4 bytes, 2 bytes, 8 bytes, etc. What is perhaps not remembered is that a compiler first compiles the program and creates an executable set of machine instructions. And these machine instructions actually is your program which is executed. Now these machine instructions typically are binary numbers. For example, 1011 may mean add. 10000 may mean subtract. You remember the Dumbo model where we said that Dumbo has a workbench in which the Dumbo has registers and he uses those registers. So these are the kind of instructions that you have. Obviously when you say add, you have to say add what to what and where to put the result. Now ordinarily at a very low level of CPU intelligence all these instructions will refer to a register. For example, it will say add register 1 to register 2, put the result in register 3. But to begin with something has to be there in register 1 and register 2 and the result in register has to go somewhere else. So there are instructions like load. So load R1 could be an instruction 0101 something something. Please note that instructions are not 4 bits. Instructions are 32-bit long. So they have an instruction code, an operation code and addresses. The instructions operate upon those addresses. Now very early in life people had to program like this. They had to write instructions like this. Load from memory location 10111100 into the register 1. Load another number from another location into register 2. Add these two. Store the final result into location 11001111. There are no printers, no nothing. There would have been instructions saying display location 1111000. And some lights will get lit. The bits will be shown. 0-bit, no light, 1-bit, 1 light. And then you have to read this 32-bit number which is your answer. Can you imagine doing that kind of programming? Now you say sum is equal to a plus b. See out sum and you get nice decibel value printed. All this happens because a compiler takes your program and translates these instructions of your program into a large number of machine instructions like this. The point is where are these instructions stored when they have to be executed? First these translated instructions are stored in a translated file which resides on the desk. When in the code blocks you say build and run, the file is taken out of the desk and loaded onto your computer CPU. And then the CPU starts executing those machine instructions. First this, then this, then this, then this. Where does the CPU keep these instructions? Or where does it find these instructions? The CPU finds these instructions in a very memory then. Now memory you had seen what I call the data memory. It is the data memory which has your variables say a, b, delta. You remember the compilation process? The names are associated with memory location. But when the program execution starts, your instructions also get loaded into another segment of memory which we might call as program memory. So it is in this program memory that your instructions 0, 1, 1, 0, 1, 0, etc. will reside. So for example if you say load instruction 0, 1, 0, 1, something, something. 1, 0, 1, 0, 0, 0, whatever. These are your instructions. The memory portion allocated to hold your program while it is executing could be anywhere physically because depending upon what memory is available to that computer operating system it will load that program. But these memory locations are all consecutive just like your statements are consecutive. Imagine that these locations are say 1,251 is the first location. 1,252 is your second location. 1,253 is your third location and so on. Thousands of locations will be occupied. Let us now discuss how the program is executed. Your CPU maintains a counter which is called a program counter. This counter is nothing but the address of the memory location from where the next instruction is to be executed. So the CPU does not go anywhere else. It just checks what is the address here. It goes to that address, picks out the 0, 1, 0, 1 pattern, treats it as an instruction and executes it. While executing it, it might have to load something from this data, add something, whatever one. But instruction execution is like. So if there are 5,000 instructions, obviously what is required is when you say run somebody which is the operating system must load into the program counter the first location of your instruction, which is this. And then the operating system tells the CPU go. So what the CPU does now? It looks at this program counter. It says, ah, my first instruction is 1,251, goes to location 1,251, takes this instruction and brings it here. This phase in electronic terms is called fetch. This is just like you sent a dog saying fetch my cup. So the CPU is telling memory fetch my instruction. The instruction is fetched and this instruction comes into what is known as an instruction register. So all these 0, 1, 0, 1, etcetera, etcetera will be written here. Just copy. The next step that the CPU takes is called decode. It looks at this instruction and decides what to do. Now what do you mean by deciding what to do? The instruction itself is executing through some electronic circuits and or not gets. Now if it has an add instruction, certain circuits have to be used. If it has a subtract instruction, some other circuits will have to be used. If it has a load instruction to get some data into a register, some other circuits will have to be used. Decode can be considered to be equivalent of configuring those circuits. Think for this instruction, do this, do that, do that, do that. This is all electronic. The CPU does that. And the last phase is execute. During this third phase, the instruction is actually carried out, where some data value is loaded into register or somewhere from register to location, additions are done, etcetera, etcetera. The matter does not end here. At the end, the CPU upgrades the PC. You understand PC++? Instead of 1, 2, 5, 1. Now this counter is increased to 1, 2, 5, 2. And that's it. The CPU now goes back to execute a fresh instruction. At any stage, it never bothers about what was the last instruction executed, what will be the next instruction executed. It knows only one rule. It has to go find out what is there in the program counter and execute that instruction. And for every instruction, it will do this fetch, decode, execute. So now you understand both how it is executed and how program counter works. Consider an if statement. If A equal to 0, do this. Else do something, something. Consider its translation. If A is equal to 0, you might get the translated instruction for those actions. Let's say 10 binary instructions immediately after that. The 11th one is else part. Now when the if instruction is executed, the CPU will do a comparison. Now after comparison, it has to execute either this path or this path. Both the paths may contain 5, 10 instructions. They are put one after another. What the if instruction does cleverly is that if the condition is true, it changes the program counter to that instruction, which is the yes part. If the condition is false, it will change the program counter to some other point saying you execute those instructions. That's it. And the CPU simply goes to execute the next instruction. So these jumps internally is what is used to implement all your conditioners. In old programming languages, there used to be a statement called go to statement. So you would write your instructions. You'll put a label against some instruction, say 10. And somewhere in your program, you will say if something go to 10. That means go to the label 10 and execute that instruction. But that created so much chaos when people were writing large programs. Everybody was going from here to there, there to there, there to there. So nobody could understand where people are going or where the computer is going. So Professor Edgar Diestler wrote a big paper in 60s. The title of the paper was go to statement considered harmful. It was banned from professional programming practically after the structured programming concepts evolved. We don't use any go to statement. We have not faced the need of it. But internal implementation is almost as if an if statement will say if this condition go to that location, if that condition go to this location. And all these locations are decided by changing the program now. Is that clear? Good. The next set of questions. What is the logic behind designing the order of precedence as it is? I appreciate this question because even I had the same doubt. So the answer to that question is as follows. Primarily the logic is that that is the kind of order of precedence that you will encounter normally when you execute those operations. Generally multiplication and division have a higher priority than plus and minus. Generally if there are operators of the same priority, mathematically you look at them from left to right. Certain presidencies which are decided that they will operate right to left, associated with right to left. Or certain presidencies are more or less. They are done both from the point of view of convention and from the point of view of proper implementation of the meaning without confusing any. The bottom line is the person who is asking this question and the person who is answering this question namely me are both positively not responsible for deciding this precedence order. This has been decided by a large group which has described the C++ language standard. Because the same question can be asked even in natural languages. Why do we call a table a table? Why don't we call it a door for example? What is the answer? No answer. Everybody knows that it is called a table. It's a convention. Once the convention becomes a rule in a programming language that needs to be added. So frankly there is no answer but the answer that I gave is close to the truth that logically we follow those precedences. There is another question. What is namespace exactly? Professor Abhinav Ranade's book which I will be shortly sending you the key. We have not been able to do that. I am sorry. A team is working on it. By the way you will all receive an email which will just give you a code number and instructions to download Atarno Reader and install it on your machine. It is on that Atarno Reader that you can read the Evo which is on the cloud. So you can start reading. He gives a very nice explanation. So let us consider the name in some context. Take for example family names. My brother's name is Sunil. He has a classmate who is also called Sunil. Now if the teacher says Sunil please stand up and three Sunils stand up. There could be a confusion. You want every name to be unique. In the context of programming, I write a function. You write another function. He writes a main program. And for some reason we decided to use the same name but which has a different meaning or connotation. Now everybody declares it in one's own thing in a single program file. If there are three declares, C++ will throw it up. We want these names to be classified as different names. So what do I do in the case of human beings? All right. My brother who is Sunil is Sunil Fadak. So Fadak is a family name. If there is another Sunil, say Sunil Chandrasekar, family name will be different. Family name is like a namespace. In that namespace, all names are unique. Hopefully Sunil will not name his son as Sunil. One hopes so. We do not know. We had a student here, a great tricker and all. His name was Vasanta, Vasanta Limayam. Father's name was Vasanth. He named his son also as Vasanth. So there was a lot of confusion when both of them were on the campus and people said Vasanth, both of them looked here. Now this confusion has to be avoided so you need uniqueness. You can consider namespace to be a label. Within that label, all names have to be unique. Now once you have this concept of a label and the facility to create a label yourself, then when I write my program, I can technically write all labels. Let's say I am writing programs in the context of CS101. I will create a label called namespace called CS101. And I will say CS101 colon colon A, CS101 colon colon B. Now this A and this B can never be confused with anybody else because that fellow will have a different namespace. That is how you write large number of programs. Now ordinarily when we are writing small programs, you don't need different namespaces. So what C++ designers did is that they said that instead of everybody compulsorily having to create a namespace and write names of the variables, I will offer a standard namespace. It is called STD. Now if you write a name in a C++ program without the prefix of the namespace label, then it is assumed that this name belongs to the standard namespace. Is that clear? This is just to avoid confusion of multiple names. Here is an interesting question. What is the maximum depth that can be achieved in recursion? For example, when I make recursive calls, effectively f of x is the inner call, f of f of x is outer call, f of f of x is outer call. So how many times I can use recursion? 2 times, 3 times, 5 times, 50 times, 100 times. I would like someone to come and answer. What would the answer depend upon? It is speculation? No, it will terminate sometime. But suppose I write a recursive function which will terminate after 1 million recursions. Will it work? And what will this value depend upon? First of all, let me tell you that the number of recursive stages that a function can go through cannot and will not be defined by a compiler. A compiler gives you a mechanism. It's almost like saying an iterative loop can iterate how many times. Compiler doesn't care. For function calls, you know you need activation records. How many activation records can be stacked? Very large number because the memory is very large. So the problem also depends upon the nature of the recursion that you have. If you have a simple recursion where f of n is something into f of n minus 1, then you are not proliferating the recursion into a large tree. If you have a Fibonacci series, we have already seen that, when you calculate Viranka numbers, f n equal to f n minus 1 plus f n minus 2. So f of 4, for example, if you start with 7 or 8, f of 4 gets calculated twice, thrice, whatever. And that creates a tree. How large can be the tree till the entire memory is filled up? How long it will take? It may take eternity if you expand it. And to understand the speed with which the complexity of a tree grows and the time escalates for execution can be gazed by knowing what is an exponential growth of a function. You remember the old Indian story of a Brahmin asking for some grain, one grain on the first square of the chess board, two on the second, four on the third. And the king was delighted. And he ordered grains to be given. And by the time you reach 32, 33, 34 spares, the kingdom was focless. And 64 spares could not be attained. That is the rate at which the numbers grow. So you want to be careful about how these numbers grow. In short, there is no limitation on the maximum depth that the compiler puts. And this is exactly what Professor Supratik also advised. Be very careful when you use recursion. Recursion is an extremely clean and elegant implementation and intuitive solution to many problems, many of which you have not seen yet. So that's a good thing to have. But simultaneously you have to worry about increasing depth of recursion and thereby increasing the number of operations that you have to perform. You should be careful about that. What is the maximum size of the array? And how to store more values than maximum size? The second question is rather funny. Suppose we say that there should be exactly one person in a hostile room. Currently that is not so. I guess there are two people staying in a room or something. Let's assume hypothetically beautiful days are here again and there is one student per hostile room. Now how many maximum rooms can hostile have is a question I can understand. But under this rule, how can I put more students in that host? So many rooms is an unanswerable question. So if you have an array of a declared size, there is no known human way in which you can fit more than those many numbers in that array. That should be very clear. That's the limit. C++ compiler does not limit the maximum size at all. It is all determined by the available memory. There is another question that I scan through, which says just like you can have two-dimensional arrays. Can I have three-dimensional? Can I have four-dimensional? How many dimensions are permitted? Again the answer is C++ does not limit the number of dimensions. So I can define an array with five elements in the first dimension, ten in the second, five in the third, twenty in the fourth. If I have a multi-dimensional data with me, I can actually accommodate in the multi-dimensional. So there is no limit that the computer imposes. What is the difference between compile and building? I suppose this comes from the code blocks terminology, right? They say build or build and run. So building is nothing but compiling. Both are safe, effectively. Building actually is one more step. When you compile, the compilation process translates your instructions into what is known as relocatable binary instructions or an object file or a .o file. Those of you are familiar with Microsoft Windows Convention, you get a .exe file which is an executable file. So .exe file is not automatically created by the compilation process. An object file or .o file is created. To this .o file are linked, several other library functions which are presumed by you. For example, IoStream or CMaths or such libraries. They are outside your compiled program. So .o object will not contain any instructions for that. The linking process collects everything together and creates a single executable which is what is executable. How to find .exe root of y using C++? Is at least asking this question in the form of how to do that. There is another fellow who is asking me. I mean, I was quite curious reading that. Write a program to do this. Write a program to do this. I felt like I am appearing for the quiz and the whole class is quizzing me. Good one, but I refuse to write a program. I wanted to ask, I wanted to find out from you what are your difficulties. So write a program kind of questions will be answered by you with your colleagues when you actually write programs. We will discuss some sample problems in you. But here is an interesting question. How pi and e are entered in C++? Now, all of you know that pi and e have values. All of you know that these values cannot be written exactly by limited number of digits. Right? So there is no question of first of all entering pi and e. You don't enter pi and e. I can actually have a variable float. Abracadabraka, some name that I gave. And I can say abracadabraka equal to 3.14159 etc. As far as the machine is concerned, abracadabraka represents a value which you think is pi. So instead of doing pi r square for calculating something related to a circle, you can say abracadabraka star r star r. There will actually be pi r square. Moral of the story is C++ doesn't give a damn as to what you mean by pi, e and other thing. It has a set of variables. It has a set of values. The values get associated with variables when you either assign that value to a variable or read a value into the variable. Now it is entirely up to you what to do. It is preferable, therefore, to use names which are meaningful. So pi for pi, epsilon for e or e for e. But there is no direct way in which you can say that because I have used such and such name, it means such and such number. That is nonsense. The name is your choice. The value is also your choice. In fact, you can try this. Those of you who are not convinced declare two variables p i, e both float. And say c in p i, c in e. Now give the value of e to pi and value of pi to e. And then do some calculations. You will amazingly find that the C++ does not complain because all these things are in your mind. Where does deleted items go in a computer? That's a very interesting question. What is meant by deleted item? Are we referring to some discussion that we had where we say delete this element from this array? Right? That could be the only deletion. Please understand that deleting an element in an array is fundamentally a human concept. When you declare an array of 100 elements, for example, inside the memory all 100 elements will have locations. These locations will have values and these values will be preserved till your program execution ends. There is nothing like a deleted number going somewhere else. Consequently, your deletion must mean you change a particular value to a different value which denotes a deleted value in your mind. C++ does not care for that. Here is an observation. It says I tried to output various variables without assigning any value to them. I expected random garbage values to be added, but the same value was printed each time. Like 19720 for integer variables, V for character variables. Why did this happen? Good question. Any answers? This is speculation, so all of you can speculate. Our friend tried this exercise without assigning any value. He asked the computer to print out the values, but every time he ran the program, he got exactly the same values. So why would this happen? I would suggest two things. One, A, run the program on some other machine. B, run the program on some other machine using a different compiler. C, run the program on the same machine by using a different compiler. You will find that different compilers and different machines may behave different here. Sadly, C++ does not stipulate anything at the level of the language. It says it is an implementation dependent feature. However, what you must note is that if you are getting a character value V for every character variable, that will be very dangerous to write a character string handling program where you assume that if nothing is initialized, everybody is V. That will not work. So if this is what is happening, it is an incidental behavior of that compiler on that day, on that particular machine. Is that clear? This is a question which we just answered. When to use a function is better or some iteration is better. Now these two are completely unrelated things. An iteration involves doing certain similar steps again and again and again. Inside the iteration, the computation that you do may still want a function to be involved. So these are independent concepts. A function invocation is go somewhere, do some computations and come back. An iteration concept is to iterate around some similar common block of code to do that repeatedly. Both may be required in solving the problem. Thank you.