 Oh, no. All right, that's weird. Come on. Come on. There we go. All right. Welcome back to, all right, welcome back to Computer Fundamentals. Thank you for joining me again today. So today we get to talk about variables and we have to rewind rewind a bit and talk again about how computers work. So programs always access memory and when again when we talk about memory, we're referring to RAM or random access memory also called main memory. Those things all mean the same thing. So we can also access long term storage or long term memory through main memory by asking the OS, but that's not covered in this course, but it's something you will see later after you have the fundamentals. Using files and things like that will be really straightforward. So we get to talk about how computers actually access memory and they again access memory in something called bytes. So recall that one byte is eight bits. You will have this seared into your memory. If you are into computers at all, that is one thing you will just, if you ask anyone in ECE, go up to them and ask how many bits are in a byte, they'll be able to tell you. You'll also be able to tell people. So if there are eight bits, that means there are 256 different representations because while each bit could be a one or zero, there's two options and since I have eight of them, there's two to the eight different possibilities. So we went over last lecture how you can actually write out a number in binary. Same principle as writing it in base 10. There's a hundred column, the tens column and the ones column. Well, with powers of two, each column is a power of two to another exponent. So instead it's the ones column, the tunes column, the fours column, the eighth column and so on and so forth. So if you use that scheme and you have eight bits, the numbers you can represent are zero. So everything is a zero, zero times any exponent and adding them all together is going to be zero. And if they're all one, that's going to be like 128 plus 64 plus 32 all the way to one using powers of two and that number is going to be 255. So in general, if we are using like the whole number representation, so numbers that are zero or positive, then if we have n bits, we can represent the number zero to two to the n minus one and that is inclusive. So that includes both ends. So if we have eight bits, we can represent numbers zero to 255. So in memory, every byte has its own unique address. That is just another word for its location in memory. And we call memory byte addressable. So the smallest unit you can actually access in memory is a byte. You can't access a single bit. You have to access an entire byte at once, which is again eight bits. So this is kind of what it looks like in memory. So each address contains a byte. So here, the blue boxes represent a byte and that is the value of the byte. And I will just write it out in decimal because we're human. So it's easier to understand. So every number in a blue box since it is a byte will be zero to 255. So below each is the address. So computers can store a lot of bytes. So the byte that has the value 50 or 57 might be at address 512,000 or something like that because it can store a lot of bytes. So this is how memory would look. So there might be different values. In this case, we have four bytes across the top and the address would just go up by one. So it's just like having an address of a house, although these just always go up by one instead of odd numbers on some street or something like that. And then we'd have four more bytes at the bottom that just continues along the same way. This one seems to have a bigger value, but it doesn't really matter. Each address stores a single byte. So any questions about that? Very important to know. In fact, for some reason, 30 years still get this wrong. So as long as you remember this, you are good. So your CPU has instructions to access memory. So an instruction can read a byte from memory. That means it retrieves that value that is stored in memory and then the CPU can access it. And another instruction can also write a byte to memory so you can transfer some information from the CPU to memory. Thankfully, in this course, you don't have to deal with that. This is why we use programming languages because that is very, very tricky to get right and very, very tedious. So this is why we use programming languages. C handles this for us, thankfully, but it's still important to understand what's actually going on and how you actually store information. So the number of actual addresses depends on your CPU. You may have heard the term, oh, I have a 64-bit CPU, and that means the CPU can address up to two to the 64 things. So it has 64 bits that is used for that address. And it's easiest just to think of that address as just a whole number. So if I have two to the 64 possible addresses, if I write out what two to the 64 is, it is just a gigantic number, which is like 18 quintillion bytes. So if I have a 64-bit CPU, I could actually access up to 16 quintillion bytes. So that's just to say computers can hold a lot of bytes. And saying 18 quintillion, no one has ever heard that representing some storage size or something like that. So we communicate using prefixes instead. You might be used to this while with normal units. So you have meters, and if you have 1,000 meters, you have a kilometer. In the United States, you have some garbage. All right. So the typical prefixes for computers are kilo, mega, and giga. So whenever we write units, if we're specifying a size of something, we write a byte as a capital B, and then a bit as a lowercase b makes sense. So the upper case is the larger one. A byte is 8 bits, and a bit is only, well, 1 bit. So we write it as a lowercase b. So you might also see this difference when it comes to your internet speed. So when you see something downloading, it'll probably be in megabytes capital B. But when you pay for your internet and they advertise a speed to you, it is in megabits. It's a lowercase b. So if you want to get the actual theoretical speed, you have to divide by 8 or multiply by 8. Or divide by 8, yeah. So they try and give you the bigger number, and if people don't know the difference between bits and bytes, then they won't know the difference. So we're used to a kilo being 1,000, but because computers are in powers of 2, we use a power of 2 instead of exactly 1,000. So 1 kilobyte is actually 1,024 bytes, which is 2 to the power of 10. That just happens to be a number that's close enough to 1,000. And 2 to the 10 kind of makes more sense to us as humans. And 1 megabyte is going to be 1,024 kilobytes or 2 to the power of 20 bytes. And then 1 gigabyte is 2 or is 1,024 megabytes or 2 to the power of 30 bytes. So old computers that your parents use that I have definitely never used because I'm that young. Well, they had 32-bit CPUs, and that means since memory is byte addressable, that means I can only access up to 2 to the 32 different bytes. So if you want to use our prefixes, we can rewrite whatever 2 to the power of 32 is using something that might be more readable to us. So using that exponent law from math, we can rewrite 2 to the power of 32 as just 2 to the 2 times 2 to the 30. And we now know that 2 to the 30 is 1 gigabyte. So in other words, this would be able to address up to 4 gigabytes of memory, which is just too small for us now. Most of our laptops probably have more than 4 gigabytes of memory. That's why we had to move away from it and have 64-bit CPUs, which as you might notice, computers like powers of 2. 64 is just the next power of 2 after 32. So C uses something called types to describe values. So I had a question of that yesterday of like, well, if like the number 65 is an A, how do you tell the difference? So types are a way for you to tell the difference of what that byte is actually supposed to represent. So a type actually tells you two things. It tells you, most importantly, to us, what it represents. And it also tells you how much memory they use. So for instance, an int is a type that represents an integer. So it's kind of a shorthand. We like shorthands in computing. And you just have to know that it uses 4 bytes because if you read the C standard, that's how big it is when they tell it to you. And this integer can represent positive and negative numbers and without any decimal points behind them or anything like that. Just a straight up number, no decimal points. So how do we actually represent this number? We kind of saw how you can take a binary number and then just convert it to a number. So well, that's kind of true. And if we have 4 bytes, that's 32 bits, so 4 times 8, that gets us to 32 bits. That means there are 2 to the 32 different representations of those bits. So if this was a whole number like we had before, what numbers could it represent? Or what is the range of numbers that it could represent? If we remember from before the generalized form of it, yep, yep, yep. So it would be close, so it would be 0 to 2 to the 32 minus 1. So it can represent any number in that range. So that would be if it was just using that whole number representation, that would mean it could represent 0 to, was that, 4 billion something. But integers can actually represent negative values, so there has to be a way that it actually stores it. So this is how it actually stores an integer. And I just write out every single bit here, so this is like our same idea of having columns to represent the value of each bit. So we have 2 to the power of 0, 2 to the power of 1. And since we have 32 bits in this case, it goes all the way up to 2 to the power of 31. So some terminology here is bit 0, the one that represents the 1's column. We always call the least significant bit because it has the smallest value. And the bit at the very end, so the highest value, in this case it would be bit 31, we call that the most significant bit because it has the largest value. But when we represent integers, that most significant bit, specifically for integers, we interpret that as a signed bit. So that tells us whether the number is positive or negative. So if that number is 0, it means it is a positive number. And then the remaining bits here represent just the whole numbers that we have gone over before. So the range of this, if these were a whole number, so we have 31 bits left over, would mean we have a range of 0 to 2 to the power of 31 minus 1. So those are the positive values we can represent. So any questions about that? Yep. Yeah, so that's a good question. So does that mean we can store negative 0? So there is a way to represent negative 0 in the olden days, but we have learned since then. So you might think of one way to represent negative numbers is, okay, I'll just take that signed bit, one means it's negative, and then I'll just interpret the rest as a number, in which case you would have negative 0 and positive 0, which would be weird. So you'll learn in 243 how we actually represent that. But it's close. It was a good idea. It was used for a time. What actually happens is that signed bit, yeah, 1 means it's negative, but the remaining bits I will not tell you about. So you just have to trust me for now that the remaining bits, well, there is 2 to the power of 31 possibilities, and there's no representation of negative 0. There's just a plain 0. So the range of negative numbers is negative 2 to the power of 31. So our entire range that we can represent with an integer is negative 2 to the 31, all the way to 2 to the 31 minus 1. So any number that is smaller than the minimum and larger than the maximum, we can't represent with an integer. We need something that has more memory. So computers have a finite amount of space, ints have a finite amount of space. In this case, 4 bytes. So we saw how to start AC program later. Some of you may have already started the lab 1 and have started it, but you are way ahead of us. So this is how you always start AC program. There will be something like int main void, curly brackets and a return 0. So now we can actually, I can actually explain this a bit more to you. So what this does is define a function called main that takes no input. So void is actually another type just like int, but it has a special meaning. It means nothing. So this says, if we take that black box model again, it says this function main has no inputs. That's what void means. And its output is an int. So its output is 4 bytes. It's a whole, while it's an integer that will be something between negative 2 to the power of 31 all the way up to 2 to the power of 31 minus 1. So that space right after the main, we can add something called statements there between those curly brackets. We usually call them curly brackets right here and right here. And the computer will run those statements in order. And computers are very, very, very stupid. They will not, they do not have a mind of their own. They will start running those statements and they will always go in order. So whenever you have to reason about your program, just remember computers do exactly what you tell them to. So they only go line by line by line is what we call it. So that return is actually also a statement. So it starts with return. And then it has a value that matches the function's output type. So zero is an integer. So that we're allowed to do that. That is a perfectly valid output to have. And all the return statement does is stop executing the function and produce an output right away. So at that point, this function is something we call, say, it's complete. It has given us an output and it won't execute anymore. And our program is done. So usually just note that usually every statement in C ends with that semicolon. You'll probably get some problems whenever you start programming that you forgot the semicolon. Don't worry about it. Just get in the habit of just putting a semicolon at the end of every line. C is a little bit annoying in that way. But it's just something we'll have to get used to. Yep. Yeah, so that's a good question. Sorry, what's your name? Daniel. Okay, so Daniel had a good question. Why does this main function output an integer instead of just void and do nothing? So that integer is actually read by the operating system to see if your program had an error or not. But in this course, we don't actually use it. So pretty much we'll always just return zero. But that's its actual use. Yep. Yeah, it's a bit weird when you start off, but it's a way to tell the operating system something. So we can actually declare, declare is another word for create our own variables in C. And they're kind of like real variables in math, but they're a little bit different in really annoying ways. So in programming languages, there is something called a syntax. You might hear that word. Syntax is just basically a set of rules you have to follow in order for your compiler to actually know what you mean and actually create a program out of it. So the syntax for declaring variables, so which in other words is the rule for declaring variables is you take, you just have a type and then you create a name and then you end it with a semicolon. So both of those words that are in the angle brackets are something you replace. So you replace that type with the C type. So the only type we know for now is int. We couldn't create a void variable because it doesn't exist, so it doesn't quite make any sense. So for now, the only valid type we could put there is int. And the next thing is just a name. So we get to name variables in C just like you name variables in math. So it has some of its own rules. So it always has to start with a letter. It can be lowercase or uppercase. We'll see what the rules are for them, but the compiler doesn't actually care. And then after you start it with a letter, then it can have letters, digits and underscores and you are not allowed to have spaces in your name. So if we go back to our C program, we can declare a variable called x. So we start int main and then the next line could be int x. So that creates a variable called x and its type is an integer. So that x will consume four bytes and it could have any value from the range we said before. So if we're saying what is going on that point, we say at the first line we declare an integer called x is probably how we would say it in English. So after when you run your program after it executes that int x line, then C sets aside four bytes for you to use for x. And now x just has a value. So instead of saying zero or one, if I want to get the value of x, I just say x. So how would that look in memory? Which is why we thankfully have C. So remember memory is actually like byte addressable. So it only stores in bytes. What C will do is just take a group of four bytes and then use that as a value for x and it will be somewhere in memory. In this case, it's the four addresses at the bottom. But you don't have to worry about it. It is set aside for you by C. So you don't have to worry about it. But it's going to be important especially later on that you understand what it is actually doing. So it's setting aside some memory for you to use for your x variable. The number of bytes it will set aside depends on how what the type is. Because the type, one of the things the type tells you is how many bytes do I need to actually store a value of that type. So if we have a variable, then we must be able to change it or at least assign it something. So we change the value of a variable through something called assignment. The syntax of an assignment statement, so again this is something that ends with a semicolon, is you take a name. So this should be a variable that currently exists at this point in the program. And then you use an equal sign and then a value. So you replace a name by a name you previously declared. And then value by a value that actually is representable by that type of whatever name was originally declared as. So this trips people up. So I will say it slowly. So note, unlike mathematics, that equal sign does not hold true till the end of time. So if you say x equals one, that's only true until you change x again. And you're allowed to change x again and redefine it in programming languages. Unlike in math, where if you say x is two, it's always two. So that might trip you up. Just remember we always have to read a program or whenever we argue about how a program behaves, we start at main and we start reading line by line in order. So computers aren't any smarter than that. If you see x equals one, that only means x is definitely equal to one at that line. So let's put it into practice. So if we have int void main, we have int x. So right after this line, x actually has a random value. So this will also trip you up at one point because if I just declare x, all c does is set aside some memory for you. And it turns out that it's not that picky. It just sets aside some memory for you and it will actually just be what it seemingly looks like just a random value. So only after I execute the next line does x actually have the value of one. So right before that, it has a random value. And then right after I say x equals equals to one, then it has the value one. Everyone good with that? Okay. So you can actually combine those two lines and do a bit of a shortcut if you want. So you can do an assignment as part of the variable declaration and then you don't have to worry about that random value. And I encourage you to always do this because typically if you have random values, it's really, really hard to figure out what is actually going on. So you should probably always use this and set the variable to some value. So it just kind of combines them together. So we can say type name equals value and then have a semicolon which ends our statement. So this statement does those two operations in one. So it creates a variable and then assigns it something we call an initial value. So that's the first value it has. That's what initial value means. So we might also call this initialization. So we might say we initialized x to one if we actually set the value to one. So our next type. So we'll explore some types we'll use in this course and then we're just going to use those types from now on. So this will be more or less the basic types you need to know. So in C there's a type called a char. So we like shortening things because we don't like typing, I guess. So char is short for character and that represents letters, digits, punctuation, something called white space which is a new term you'll probably haven't heard before and also something called control characters. So white space is just a fancy word to kind of group a whole bunch of things together. So white space means spaces, tab characters and return characters. So basically just things that change where characters actually are but are not actual like things we can see per se. They just kind of move things around. And the other thing is control characters, those you definitely can't see but they usually do something. So for instance a tab like the tab key generally moves something a few spaces but we can't see it. It's nothing we could print on the screen. It's called a control character and also your return key or enter key is also another thing that goes to the next line that is also represented by a control character because it's not something we can directly print on the screen. So a char, remember types need to tell you two things. So a char represents letters, digits, punctuation, white space, control characters and then the next thing a type tells you it's its size and the rule for char is they are always exactly one byte. So they're always that one unit so we only have 256 different representations. So how we define a char value they start and end with just a single quote. So a char is only a single character remember we can't we can only have one at a time. So you could declare something called char C and then set it equal to single quote capital A single quote and then well as we learned in the last lecture well a actually gets a magical number associated with it so that would actually store the bit 65 but you don't really have to know that. So we need to be able to type out those invisible characters so they're called non-printable characters so we need to be able to say that a character is like an enter key or a tab key or something like that but we can't just press enter because it would move to the next line it wouldn't fit just within our single quotes. So in order to represent an enter key or something like that the rule is we need to prefix them with a backslash character and that tells C that well this represents a character that you can't you can't represent and the next character you type after that will tell C what it actually represents and not literally use that character. So this backslash is called an escape character it's basically a word to tell C hey I mean something weird here so just look at the next thing I type that will tell you what I actually mean we're breaking the normal rules here. So Wikipedia has will list all of them the only ones you'll use for this course are you probably will never even use the tab character but to represent a tab character it's this backslash t they generally just start with the letter that they're supposed to represent a new line is backslash n so this is the return character and we saw that that's what ended hello world so it was hello world and then backslash n so the convention is whenever we're done with a line you put a new line at the end of it to go the next line so you can also think of it as hitting return or you know sending a message so if you want to send a message to your friend or something like that or you send a message on discord you type what you meant and that won't send until you hit enter same idea for C you want to always do that enter character whenever you're done if you want you might notice that oh well if backslash is an escape character how do I make the character actually backslash so in order to represent a backslash you do backslash and then backslash so that means well I'm using an escape character but I really meant backslash so it's kind of weird but you'll get used to it and then well if a single quote starts it and I want to represent a single quote if I didn't have an escape character it would be like single quote single quote single quote which wouldn't quite work so to actually represent a single quote it's a single quote then backslash single quote and then a single quote to end that character again it looks a bit ugly but those are just the rules so we can also interpret that charge like we said before as a whole number so remember a byte can represent a whole number in the range 0 to 255 it just depends what that byte actually represents and that's exactly what types are telling us but under the hood in memory they're just being stored as ones and zeros it's only how we interpret them that gives them any meaning so which of those byte numbers corresponds to which character is defined by something called ASCII so it's short for the American Standard Code for Information Exchange it's a very exciting acronym so ASCII you'll probably hear people use that term a lot it only uses seven bits so that most significant bit of that byte is always zero and that would correspond to whole numbers in the range zero to 127 because we only have seven bits to use for our ASCII character but that turns out to be more than planning to represent the number of characters on a standard us keyboard it is a very us centric thing in order to represent characters in other languages that is a much more much more complicated topic so for now you can look up the values if you want on like ASCII table dot com again printing non-english characters out of the scope of this course we've only finally agreed on how to do it there was like 20 different ways to do it before but it's kind of it's more or less standardized now okay our next type is called a double and that represents a number that has a decimal point so if the rule in C should always be if you don't require a decimal point you should use an integer if you do need a decimal point you need a double and a double is eight bytes and the reason why it's called a double is because well there's a less precise version called a float and that's short for floating point it has to do with the way computers actually represent the decimal point so they move it around or they can move it around if that doesn't make sense don't worry you'll learn how they are represented in a later course not this one but just know that well there was something called a float it represents something with the decimal point in this course we won't use a float we're only going to use doubles so a double is just double the size of a float that's why it's called a double we don't really have good names in computing I don't know why so all you need to know though is that a double represents an integer with or sorry a number with a decimal point and it takes up eight bytes so for example if I wanted to create a double I would say like double pi and then equals to three point one four one five nine two so on and so forth so that is how you would define a double so the last type you'll be using in this course is called a bool it is short for boolean and a boolean is just a name for a value that can either be true or false and those are the only options so if it can only be true or false we talked about that before that should be like that light bulb it should only be one bit but in practice since memory the smallest unit of memory is only a byte a bool still takes up one whole byte so there are certain situations where it can lead to a faster program so if what you're trying to represent can only be two different values true or false then you should use a bool otherwise you should use one of the other types so by default you can't use the bool type if you just type it you need to add include std bool again that's short for standard so standard bool dot h to the beginning of your code and then after that you can define a boolean like this so bool is knowing equals true or your other option is equals false and with booleans you only have two options and why you need to do this is apparently booleans didn't exist in the 70s whenever they first came up with the c language they added it after the fact so all of the previous types except for bool are enabled by default so you don't have to do anything special in order to use them so these default built-in types are something called primitive types you might hear that term being used and for now in this course up until probably way after the midterm we're only going to use the types in char double and bool and that's it so after a while there's some other built-in types we'll see some more of those soon but for a good while this will do us for now later in the future we will also create our own types which is a lot of fun but that is something to look forward to later so when we develop software this is our usual development cycle so we start here by editing some code we think we have some great idea we think it's going to work so our next step and you might have already done this if you've started the lab if not don't worry about it so you edit some code and then we compile it and then well that code can either compile or it cannot so we get to a decision here which is that diamond shape so we ask ourselves well was that correct or not if it was not correct that means the compiler gave us an error or in other words it's telling us something is wrong and it actually can't create a program for us so if something bad happens when we're compiling we call that a compile time error or a compile time problem we have some issues when we're compiling if we successfully compile so we follow this decision here we're able to run our program so you might try running your program and then when you run your program then you check if it's correct if it produces the correct output that you expect if it doesn't well then that's something we call a run time error you know it might be something wrong with how you structured your program or how you thought about it or just something weird might be going on in if something is wrong well then you have to go back you have to edit your code change something try again go over the whole cycle again and again and again until eventually you run it it's correct and then you're done that done probably shouldn't exist because software is almost never done so just ask microsoft so compile time errors means you cannot create a program the compiler failed at some point so we can actually introduce an error ourselves to see what happens so if i start off by saying main void and then my first line is x equals one while whenever the computer runs this it will start executing it from line by line from top to bottom so if my first line is x equals one well it doesn't know what x is we haven't created anything called x at this point in the program so it has no idea what it is so we'll probably see something like this where we get an error and we get some weird terminology here that you haven't seen before it says the use of an undeclared identifier x so remember c runs like line by line from the start of main so if we break down this error a little bit this undefined x dot c that's just the name of the c file your c source code file usually they'll always end in dot c that's the extension for c and then it will have a colon followed by a number so that first number after the file name is the line of the error so if you start reading it line by line on visual studio codel also tell you what the line numbers are on the left hand side so that is the line of the error and then the second number here is the column of the error so wherever that error actually is and then it will tell you error in red basically the rule is if you see red you're dead so it did not work so that just means there was a problem at something it couldn't actually compile your program so in this case this error means we cannot assign a value to a name that does not exist so identifier is just a fancy compiler word for a name and in this case it's telling you that the name is x so use of undeclared identifier if i translate that to you in english it means that the variable x does not exist all right any questions about that okay so let us see it for ourselves okay let's not see it for ourselves sometimes visual studio code does silly things why visual studio okay here we go we are back so we can have something like this so this is the same thing we have before we have it main we have x equals to one and if we have something like this this should be a compiler error so your compiler may give you a different result but it will translate to the same thing so i have a little bit of a shortcut here where i just type compile instead of hitting the button because that's a bit more clear to me so it will try to compile it and then give us that error and it points to it says use of undeclared identifier x so we can verify that if we go ahead and we change it around so we put in x above and we go to compile it again it just gives of some warning that x is set but not used so the compiler is actually a fairly smart piece of software and it will give you warnings that you're doing something that is not quite right so what this is saying is that you don't actually use the variable x for anything so why did you create it in the first place but we don't really know how to do anything else uh any questions about what we have so far or want me to do anything silly with this program so something we oh yeah so yeah so it'll just at this point right here where my cursor is like whoops so right here x will just have a random value and we don't know how to print it yet so that's the next lecture we can print it in the next lecture but for now it will just be a mystery so we don't know enough to do anything that exciting yet the only thing we could do is we could get rid of this warning that says x is set but not used because what we can do is well all right we're not done yet so main returns an integer right so x is an integer so instead of returning zero well i could return x if i really wanted to so if i did this i should not have a compiler warning because i created an x i set to one and now i return x so i'm returning one from the value from main which is a bit weird so we should probably set to zero to just go with how we're doing it in this course but this means the same thing except that c is going to go ahead and set aside some storage for x for us all right any questions from today all right so we don't know enough to do anything silly next lecture will be the first fun one where we can do some really silly things so just remember pulling for you we're all in this together yep one second