 Good morning and welcome back. So, we were talking about character strings and we said that the traditional way of representing character strings in C is to use an array and to indicate that such an array contains a string, a null value is stored in the location immediately after the last character of the string. This then is the standard way of handling character strings. It is interesting to remember that most modern programming languages actually permit a type called string and variable length strings are stored and managed internally by the compiler and the compiler generated instructions and we have library functions in these languages which handle complete strings each string as a single entity. However, we do not have such luxury when we use C programming language where a string necessarily consists of individual symbols and with a backslash null as an artificial character enter at the end of these symbols. Consequently, managing string becomes a bit of a problem in C programming language. It is for this reason that the language supports a huge library which can handle strings called string dot h. Here is the example of a name array again an array of 60 locations. It can hold 59 characters. This was the query that some colleague had asked that what is the length of the string that can be stored? The length of the string maximum length of the string that can be stored can have 59 characters. However, as I said, we always define strings to have sizes which are far more than the actual number of characters in a string that we will ever be required to store in that array. Consider for example, Rajesh Mashruwala to be stored here. It will be wrong to use the word assignment like this. S name equal to Rajesh Mashruwala. Such an assignment operation is invalid in C. Although in C++ in most other languages it will be valid where S name would have been declared to be a variable of type string. Such a variable of type string does not exist in C and therefore each location has to be assigned a value which is one symbol. For example, somehow we must ensure if we want to store the string Rajesh Mashruwala in S name 60 array, then we will have to ensure that R goes to 0th element, A goes to first element and so on. The blank that you see here is also a symbol. So, including this blank if you count there are 17 characters here. These 17 characters will occupy positions in S name array from 0, 1, 2, 3, 4 up to 60 and the 17th index which is the 18th element of the array will be required to be containing a backslash 0. So, we will have to insert a backslash 0 ourselves. Such strings are called non-terminated strings. I repeat, they are artificial entities. C programming language itself does not directly deal with string as a value. It deals instead with individual symbols stored inside array elements, consecutive array elements. However, it permits us an additional feature namely it permits us to insert a special character at the end of such a string so that later on we can figure out whether the string has 5 characters, 17 characters, 28 characters or what needless to have. If I have a string which is larger than 59 characters, I cannot store it in this array. I will require a larger array. Consequently, it is the responsibility of a programmer to ensure that whenever he or she is dealing with character strings then the array which is defined to hold the string has adequate number of elements. So, we note that an array overflow may occur against which our program must guard. We must check that an index i in s name i does not exceed, does not cross 59 while dealing with meaningful symbols. Since a string is stored in this fashion and since it is not a predefined data type in C we cannot perform normal operations like assignment, comparison, concatenation, etc. All these operations must be done by writing program code. This is the important issue with C programming language. In all other cases of data types for example, whether I am dealing with integers or floating point, I can assign these values to a variable, I can operate upon these values, write expressions involving these values, manipulate these values through instructions in C. But as far as strings are concerned there is no direct assignment of a string, there is no direct concatenation of strings which is the operation possible on a string. Consequently, if I wish to determine the length of a string stored in s name then I will have to write a program code of this type. For i equal to 0 s name i not equal to backslash 0 i plus plus. Not this is the use of a for iteration construct which does not do any meaningful work at all. It just continues to run this slide. In fact, if I have null statement here, if I just terminate for i equal to 0 s name i not equal to backslash 0 i plus plus and that is it. When I come out of this loop either I would have completed the entire scan of the array or I would have hit upon a backslash 0 and whenever I hit backslash 0 that value of i represents the length of string. So, the length consequently is equal to i. I understand that there is a query what is the ASCII value of enter. This is a query made by a colleague from SGSITS. Unfortunately, I do not remember the ASCII table, but ASCII table is part of information in most textbooks. I would request you to just look up the ASCII table which will tell you what is the code corresponding to enter. To the best of my knowledge, enter I think does not correspond to an ASCII character. Enter is a code which is used by human interaction to indicate the end of our thing. Of course, there is a code which gets transmitted to the machine. There must be an ASCII code. Unfortunately, I am not able to tell you what the code is. C. Hager Institute of Technology, Pune has a query. If I declare int x 555, then what is the size of x 00, size of x 0 and size of x 0. So, what is the size of x 00, size of x 0 and size of x 0. This is an interesting question. The question asked by the colleague from C. Hager Institute says that if I have a declaration int x 555, then the question is what is the size of x 0, x 00 and size of x. So let us look at this particular question. The correct answer is that there is no notion of size of x. There is no notion of size of x 00. There is no notion of size of x 0. We must remember that when we declare an array of this type, we are actually declaring a collection of several integer values. To be precise, there are five elements in the first dimension as five lengths, second dimension is five long, third dimension is five long and therefore there are totally 125 integer values. The size is associated with a data value which is stored inside the computer. Unfortunately, the English word size has connotation for any collection and therefore we may speak in terms of size of the array x. Logically, size of the array x is 125. By that we mean it is a collection of 125 integer values. But if we take the word size in the technical sense that is used for describing size of the data types, this question is not very meaningful. We can say what is the size of any individual element. For example, x 13 0. This is one element which has the first dimension index as 1, second dimension index as 3 and third dimension index as 0. This element contains an integer value say for example, 51238. Since this element can be assigned an integer value, the size of this element is always the size of it. So, I would like to repeat whenever we speak of size in the context of the data value representation, size always refers to the size of the memory that is allocated to hold a value of a particular type. And therefore, independent of how this array has been declared and what are the dimensions, the size of a value held in an individual element is always the size of it because that is the data. If we declare this array to be clear, then the size of an individual element would have been 1 by. So, to conclude it is wrong to talk about size of x, size of x 0, etcetera, etcetera, etcetera. Although you will get a size and that size will probably be the size of the total memory conglomeration or the complete composite that is represented by that value. It is useful to talk about the size of structures. When we introduce the notion of structure, we will see the extended notion of size. I would rather answer this question at that point in time because there is indeed a size associated with any collection of bytes. To the extent that x 0 represents a certain collection of bytes, x 0 0 represents a certain other collection of bytes which is actually a subset of the elements in this array. When we discuss struct and when we discuss the size of struct, we will describe these things in greater details. Right now, I have tried to introduce the concept of size limited to the size of an internal representation of a data value. Why C does not perform bounds? Using turbo C compiler, we declared a string of size 20 and we gave a name of size 30. We were able to read and write that. How is that? Wonderful. The question is using turbo C compiler, somebody defined an array of size 20 and pushed in a string of 30 characters. We were able to read that and we were able to put that string inside and we were able to read it back. How is that possible? Let me assure you that it may be possible to do exactly the same thing with any compiler for the simple reason that C programming language does not check for array bounds. Let me explain because this is a very interesting question which actually indicates the possibility of a very funny flaw that might get into the execution of your program. For the sake of gravity, instead of using an array of size 20 and an actual string of 30 characters, let me use an array of size 5. Let me show how will this array look like. So ordinarily I should be able to put only four characters inside and this should be backslash 0. Please remember that while array s has this memory allocation, there will be some memory before this and there will be some memory after this. It may be that I have declared a care array and then I have declared some numerical value n, some element i or whatever. All of these variables will get allocated memory locations. So while only these 5 bytes will be allocated to this memory, the other subsequent adjacent bytes will get allocated to something or the other. Imagine what will happen if instead of putting a 4 character string, I put a larger string here. Let say I put a string which contains 8 characters. So for example, what is an 8 character easily? Let me say I try to put IIT blank Bombay as a string and I try to push this string in. Note that I am not showing an assignment operation but I say I try to write this string in the array s. How will that be written? I will be putting one character at a time in an element. So I will put in this 0th element the later i, first element index first i, index 2 t, index 3 blank, index 4 b. Notice that c programming language does not check that I have already completed utilizing all the 5 elements of the array available. So when my index becomes 5 and I push o here, index becomes 6, I push m here, index becomes 7, I push b here, index becomes 8, I push a here, index becomes 9, I push y here and I put the backslash 0 in index 10. C programming language actually permits me to do that. So this is not a characteristic of turbo c. This could happen in any implementation of c because c does not check ranges of arrays. But what would happen is suppose these locations, let us say this location actually was allocated to let us say an integer variable n and I had assigned a value let us say minus 258. Then what will happen is that minus 258 value will get obliterated when I write these o, m, b, a, y, backslash 0, etc. So writing will be permitted by c. What about reading? Well, any c program which tries to read the string in this array will start with an index 0. And if I am trying to determine the length of the string or if I am trying to determine when the string ends, I will be looking at consecutive locations and try to examine whether any location has backslash 0. Unfortunately, since I have inserted this string, there will be no backslash 0 here, here, here, here, although the string has ended. There is no backslash 0 here, there is no backslash 0 here and my program will suddenly find a backslash 0 here because I have written that there. And I will therefore be able to read this string as IIT Bombay. What I have done is I have cheated the c compiler. But in the process, I have also cheated my friend the variable n. The variable n which contained some value which was assigned by some operation either input or computation will now be completely obliterated. And the value that n will show will be something completely different. That value will be the equivalent of the representation of the bits which constitute symbol O ASCII code, M ASCII code, B ASCII code and A ASCII code. So the truthful answer to this question is if I am able to write and read a larger string than what I have declared, then I am also obliterating some other memory location here. In fact, these days thankfully you have memory protection across programs. But suppose you take a contiguous memory and imagine that the boundary of your memory ends here only. And that here is some friend's program which is running here. Another program P2. It is possible in a multi-programming environment. Not on an individual PC. It will not happen. But what this would mean is you are actually insulting something into your neighbor's location. And the neighbor's program may get chewed up. This is a very drastic consequence. So I am glad that this question was raised. And the correct answer to this question is that while you are able to put 30 characters in a 20 character string, it is grossly unfair to do so. It is like saying that I have a home which has three rooms. But instead of putting my furniture into three rooms, I have put the furniture in five rooms. Three of my own house and two of my neighbor's house. And I am able to see that furniture, use that furniture, put that furniture in and get that furniture out. All that it means is I am illegally occupied two rooms which belong to somebody else. I think that is the best analogy I can think of. What is N-bit computer architecture? N-bit OS and N-bit compiler and size of data type depends on this. We are digressing from the character string handling. However, I will answer this question partially. This is a question about computer architecture really. And invariably when we talk about N-bit computer architecture, this N refers to addressing capability of the machine. So when we say 16-bit architecture, it means that the intrinsic native ability of the computer to address memory is limited to 16-bits. That means its native address space is 16-bit. In fact, 16-bit computers were the early microprocessors. Most of the computers that you see today are 32-bit computers. So we call them 32-bit architecture. In most programming languages when they are implemented through the compilers, compilers necessarily tend to use the native address space of the underlying computer. As I explained earlier, that is the reason why you see most of the sizes of your normally used variables as integer and float to be 4 bytes. And that is because 4 bytes would be the word length or intrinsic word length capability there. There must be a complete separation of addressing capability and discussing the word length. So when we are talking about sizes in compilers, the sizes relate to the groups of bytes that can be collectively addressed by the higher level language abstractions. When we talk about the computer architecture, the architecture bits refer to the addressing capability. It is once again I would remind that on a 32-bit computer architecture, I can actually have a physical memory which is much larger than 2 to the power 32. Just as in a 16-bit architecture, I actually had memory larger than 2 to the power 16. The rest of the memory is used by operating system which handles memory management and allocates different segments of memory to different programs which may be executing simultaneously in a multi-programming environment. But we shall discuss these things at a later stage. First I will go to VNIT in Akhpur. In your program of string length, you have returned single length value as I. Should it be I or should it be I plus 1? Very interesting question. Let's go back to this slide. This is the slide our friend is referring to. I am returning length as equal to I. Why am I doing that? Well, notice that in C programming language, the index starts with 0. So if I have a string of length 4, the 4 symbols will be stored in locations 0, 1, 2 and 3. And the 4th location itself, the index 4 itself will contain a backslash 0. When I am talking about the length of the string, I am talking about the total number of meaningful characters in the string. Curiously, if I is equal to 4, then while the 4th index value will be backslash 0, but the locations 3, 2, 1 and 0 will contain those 4 characters. And therefore the code is correct. The length of the string stored inside will actually be equal to I, where the if element is backslash 0. This is happening because the string index starts from 0 in C. I hope that answers the question. Let's go to Vijay T. I. My question is, if you would like to display something by using printup or bootcar or bootstrain something, then we have to use semicolon. So my question is, can we display anything or something on screen without semicolon? Not semicolon really. Semicolon actually in C programming language indicates end of statement. So this is the semicolon for example. I did not exactly get your query. If perhaps you can type it out and show it in the chat window, what exactly you mean, I will try to understand. But better, let us differ this question because I will be discussing printup, bootcar, gatecar, etc. when we discuss the basic I over Monday morning. So we will differ this question. There was one more query from somewhere. Let's go over to COEP Pune has a question and ASC Amrutapuri has a question. We are going to ASC Amrutapuri. Please ask your question. Hello sir. This is Praveena from Amitapuri. Actually when we write a program using file, there is an end of the file and I would like to know what is the ASCII value of the end of the file. The FGHC will return a macro which is EOF while reading from the file but what is the ASCII value which is there at the end? Good question. The reason is something completely different. You see EOF does not have an ASCII value per se. So other colleagues will recognize that EOF is a spatial symbol. EOF is in fact neither a printable character nor is it associated with an ASCII value. It is interesting to note that when we say get care or any file operation actually reads an integer value. So internally the value represented is not limited by the ASCII codes of the characters that we put in. C programming system uses this fact that what it is actually reading is integer. So even when I say get care, C for example. I think that I am feeding one character at a time which it is reading. Yes, it is indeed reading a character as I type in but what it stores internally is not just the ASCII value of a character. When I put an actual symbol like A, Z, P, 5 whatever it will store the ASCII value but whenever I press an end of file it will pass on a spatial value which is an integer number but not a valid ASCII value. In fact if EOF was to have any ASCII value that would simply be recognized as a valid character by the get care system. The very fact that C programming language is able to terminate my input is because it can recognize this EOF as a character completely different from all possible characters that I can use and therefore it is not really a character. What the file system does is it provides a spatial value. This value by the way will not be available or understandable from your hex num. It is defined in a header file separately. In stdio.h you will find this definition or in some associated file. So to recapitulate EOF is not a formal character and therefore does not have an ASCII value. See compiler cheats because when it reads characters from a stream it actually stores these as integer values. If it is a proper ASCII value it will store in one byte of the location that you have allocated for reading characters. But if it is an EOF internally it has an integer value which says oh there is no character it is end of file and therefore it will terminate the operations. Where are we going? COEP? No COEP? Yeah we could not go last time. Good morning sir. We are from COEP. Sir my query is regarding underscore bool data type. In traditional C language any non-zero value is treated as true and negative value is treated as false. So with the introduction of underscore bool in the latest C still that rule holds good or any logical or relational expression gets evaluated to an underscore bool type like Java. Good question. The underscore bool should be regarded mostly as an internal data type. I indicated it only because I am talking to colleague teachers and not to the students. While introducing C programs it is useful to continue to stick to the classical definition that a value zero is false and any non-zero value is true. That is the definition that is mostly used. I indicated it merely to suggest that standards have evolved. I am not sure that all compilers by the way implement and recognize this. So therefore the boolean or bool type should its usage in my opinion should be restricted to programming languages such as Java or C++ or Csharp. But as far as C programming is concerned it is useful to tell people that any non-zero value will be treated as true and zero value will be treated as false and if at all you introduce underscore bool the correct way of stating that is that the bool variable represents a value true and false. It may incidentally so happen that false value is internally represented by zero. The true value in most implementations I know will be stored as one by the way, integer value one. But traditional C says any non-zero value is true and I suggest that as far as our students are concerned we should continue with that explanation. But thanks for this question. Anna University has a query and Somaya has a query. We will go to these. For finding the length of a string you have used a continued statement and with two variables. My question is can we not rewrite that function as or that code as for length is equal to zero S name of length not equal to null character length plus plus and semicolon. Over. So I hope you can see that I have actually written this code. Unfortunately I do not have the compiler environment here but you are absolutely on thought. In fact this will be a very short and sweet code to determine the length. So I have written this code for you. I do not need int i anymore for length equal to zero S name i not equal to backslash zero length plus plus. I compliment my friend at hitting out a very sweet and short code. There is however only one problem with this code. And that problem is that if for the entire length of the array I do not see any backslash zero. There is no termination possible here. In fact it was not possible even in the code that I had written. This merely shows how all of us can forget the basic discipline of checking array bounds. But mostly we shall be using arrays in which we would have put some strings of a length. While putting the string we would have taken care of checking array bounds. And therefore this code to find the length of the string is often adequate. Suffice it to say that if I am inputting strings from a file in which I have not pre-validated the length of the strings I am giving in. Then I should perhaps check for the size of the array. But otherwise this code is perfectly fine. We have one more question. I just wanted to quickly show an example. But we will go over to KJ Somaya and then we will continue with this. Hello sir. Sir my question is what is the significance of signed characters? What is its actual application? Like for characters why do we require signed database? The question is why do I have the signed care at all? There is actually an unsigned care and signed care. There is just as you have an unsigned int and signed int. Suffice it to say that the behavior of signed and unsigned care is exactly similar to signed and unsigned int. Except that the size is different. For care the size is only one byte. As I mentioned some time ago when I deal with care actually I am dealing with an integer value. For my sake the value is a symbol which is represented by an ASCII code. But as far as C compiler is concerned the care type by the way is identified as a numerical type only. And it is described in the standard as part of the numerical value type. So int, small int, long, unsigned int, signed int, care, signed care, unsigned care are actually treated by the C language as integer values. The difference between signed care and unsigned care is that unsigned care since it can represent values between 0 to 255. Whereas signed care can represent values between minus 127 to 127. We have to be careful in what values we assign. Normally a signed care can store 127 ASCII values so it is good enough. But if I want to store some additional special symbols and special characters I will have to use an unsigned care. Consider for example if I want to store pixel values which have absolute values between 0 to 255. It is useful to use unsigned care as the location. Otherwise there is not much difference but your point is right. The application will depend upon the domain for which I need to specially treat certain values. Otherwise there is no difference. As far as we are concerned my recommendation is that when you teach your students while you may mention such peculiarities at some stage but it is useful to inculcate the following discipline in them. Whenever they are talking about character arrays and storing characters symbols which are visible to us they should simply use care. Never bother about unsigned care, signed care or whatever. So these are not relevant and unsigned care is relevant whenever I want to store special information such as digitized pixel values or digitized audio values etc. HGS-ITS is a query. Can we quickly go over to HGS-ITS? The program requires something around 16 bytes. Now what I say is it necessary for the program for the compiler to check whether 16 bytes are free first then only allocate the memory or what if there can be a situation where we can have scattered locations free where in total we have 16 bytes free but they are not continuous. So is it possible to store the values of those memory variables where some of them are integers. MNN are integers whereas the array is continuous. So for the array I agree that it has to be continuous. But what about the memory variables MNN? Thank you sir. The question actually relates to memory allocation and the fragmentation of memory none of which are directly relevant for the compiler question. First of all I would like to assure you that when I write a C program the C compiler allocates memory. The C compiler there is no question of memory being available or not available. Please understand that when the C compiler is compiling your program it is not putting anything into the actual memory location. That happens only when your translated program is loaded into the memory by operating system. So consequently let it be correctly understood that as far as compiler is concerned and compilation process is concerned there is just no notion of fragmented memory. Compiler while translating will always assume that it has contiguous memory available for allocation and that is how it will allocate memory. So the distinction that we make is memory allocation made by the compiler and the actual memory physically allocated to the program after compilation when the program has to run. Incidentally when a program has to run even the operating system will allocate contiguous memory. The kind of fragmentation that you mentioned typically happens inside a disk and if it happens inside the main memory it will happen in chunks. It will never happen in terms of a few bytes going missing here or a few bytes going missing there. So in a nutshell when a compiler is allocating memory to your variables compiler will always assume contiguous memory. As a matter of fact it may leave a few memory locations blank if it wants to align the memory allocation around certain understood boundaries such as word boundaries. We shall see this notion when we look at the struct and the size of the struct later. But I would like to clarify that there is no notion of fragmented memory when compiler is allocating memory because compiler is not putting anything in the real memory at all. Every compiler will always assume that the memory allocation it does will be in contiguous memory location. That is how the memory allocation will be done. We will break now. So thank you very much.