ROB: All right. Welcome to the first section. I'm Rob. JOSEPH: I'm Joseph. ROB: So we'll dive right in. First thing to talk about is the Appliance. So hopefully most of you have downloaded it already. But you can see the instructions at cs50.net/appliance. Oh god, now I'm self-conscious. I still hear it. JOSEPH: Wow, it sounds like it's disoriented. ROB: So some people have been having issues with it, so don't wait until the last minute of the problem set to try and solve the Appliance and finding out that it's not working. JOSEPH: And if something's not working and you need help, you can go to cs50.net/discussion where we have a forum where you can post your questions. And we'll get to them eventually. ROB: All right. So this is what the Appliance looks like. Again, it's just a completely separate operating system running within whatever operating system you are running on your laptop. And the main things you'll be using are gedit. So hopefully this has already become a familiar site. The terminal. And you can also run Chrome within the Appliance. There have been a couple of people who have reported internet not work in the Appliance. And some of them have just assumed that there isn't supposed to be internet in the Appliance. But yes, there is supposed to be internet. I'll say it right now, but it doesn't really mean anything. If the internet isn't working, this is what you tend to need to run to fix it. If you are having internet issues, don't remember it, just post it on Discuss, and we'll say, run that. But the internet should be working. So the only other thing-- yeah, nothing else is really relevant. But I just wanted to point out that-- see in this bottom-right corner. So each of your Appliances should have an IP address. And later in the semester, this IP address will become more relevant when you're working on the web p-set, because you'll be able to access the website you're working on from your local Chrome by using this IP address. But what I like to use the IP address for-- and you don't have to do this, I just want to point it out-- is here. So this is a terminal window on my Mac, this is not in the Appliance at all. And you can look up what this command does. But I'm going to SSH directly to my Appliance. I don't know what the IP is. JOSEPH: 168-- 168.224.1.0. ROB: So once I'm done with this, log in. Now, basically, this is identical to a terminal window within my Appliance. So I pretty much never actually worked from within the Appliance itself. I just always have it running in the background minimized and SSHed into it. The issue with this is you are not going to be able to use gedit easily directly from this. But if you want to be a real cool hacker, then you should get used to a command line text editor anyway. So Vim and Emacs and Nano, all of these are different alternatives. Nano tends to be the easiest. And I think it has no syntax highlighting. Oh, no, it totally does. So you can use Nano, because that one's pretty easy. You see all these commands at the bottom. This little carrot symbol. If you haven't seen it before, you'll probably see it a lot now. It generally means the control carrot, like the bottom-left of your keyboard control character. So here it's telling me down here-- oh, it's not cut off if I zoom in. So Control, X is how I'm going to exit. And it says I can hit Y for Yes, for saving, N for No. So that's Nano. Vim and Emacs tend to be slightly more complicated and overwhelming. But you can get used to it, and then you'll love it. So that's that. JOSEPH: No need to do that. ROB: Yeah. You are free to use gedit for the remainder of the semester. So any appliance-related questions? Or do you have any thoughts on what else needs to be spoken about about the appliance? Yes. SPEAKER 1: When you SSHed into your thing, was the password Crimson? ROB: Yeah. The password for pretty much everything in the Appliance is going to be Crimson. SPEAKER 2: Install like a real IDE on the appliance, will it work? ROB: I imagine Eclipse does have a Fedora version, in which case, yes, you can do that. It's probably not really worth it. SPEAKER 2: OK. So it's probably easier if I wanted to use Eclipse, just use the native and then upload to-- ROB: Oh, that is also probably easier. But you can get it working within the Appliance. JOSEPH: And for the camera, the question was, can you install another IDE inside of the Appliance? ROB: Eclipse being an example of an IDE. Any other Appliance questions? All right. So we will now move on to command line interface-related things, so CLI. And again, I'm just going to work in here, because this is identical to working within a terminal window within the Appliance. How's that font looking? Is that big enough? All right. So there are a lot of commands that you should get pretty used to throughout the semester. The big two for navigating are ls, list the files in this directory; and cd, so change directory. So I can change to desktop and then a very common pattern is cd to a directory and immediately ls what's in the directory. People also sometimes don't realize that Tab completion is a thing. So like cd, vh, and then I hit Tab. I almost never type out the entire thing. And then if I keep hitting Tab again, it'll automatically start listing for me. So I can cd vhosts, local host. And that's just going to-- in case you have not heard the term before, directory is just another word for folder. So now if you see-- let's bring that to the top. So now if you see in parentheses, you see the little tilde, slash, vhost , slash, local host. So the tilde, that refers to my home directory. It's a directory you're in when you SSH in. It's the directory you're in when you open up a terminal. It's where you start. And so I'm inside of my home directory, and I'm inside of the vhost directory inside of my home directory. And then I'm inside of the local host directory inside of that. So some other useful things with cd-- or well, in general, so dot always refers to the current directory. Cd, dot is a pretty worthless command. But that's changing to the current directory. A more useful one in terms of cd is dot, dot, which is just go up one directory. And note that these-- I want to say aliases, but these symbols, dot, and dot, dot, those work for pretty much any command you're going to be thinking of running. So like cd is probably where you'll be using the most, but these aren't things that just cd understands. It's pretty much something your entire command line understands. A lot of programs understand dot and dot, dot. So the other useful ones-- cd, dash. So that is going to bring me to the last directory that I was in. So sometimes I'll do something like, oh, I'm working in here. And I see some error with something, and I'll go investigate it by going to some random directory somewhere. And I don't know if it'll let me in there. It will. So then I do whatever I want in this directory. Blah, blah, blah, blah, blah. And I was like, all right, I want to go back to where I was. cd, dash, and it brings me right back. So I'm going to throw a lot of these at you today. I don't expect you to memorize all of them. It's kind of just know that they exist. And then later on when you're like, hmm, I want to go back to the directory that I was just at, oh, wait, something like that exists. You don't have to just type in the entire directory again. JOSEPH: And eventually you will just use them over and over again, and it'll become muscle memory. ROB: Yeah. So how I said before, that tilde is your home directory. So I can cd, tilde. But I don't even have to do that if I just-- I'll go back to the directory so it's not a pointless example. But if I just do cd, that's also the same as, go to my home directory. I do Command, K. JOSEPH: You can also type clear, the word, and it should clear it. ROB: And I think also Control, L also does it. So lots of different ways. I think there are some differences where clear and Control, L will just really push it to the top and I can still scroll back. Command, K literally destroys everything, and you cannot scroll back up. At the very least, that's how it works in iTerm2. I don't know how other things-- oh. With SSHing, so if you are on Windows, you're going to have to download PuTTY in order to SSH since Windows does not have like a built-in SSH tool. From Macs, you can just SSH directly from a terminal window. OK. Questions? With ls, so something to get used to with most of these commands is-- well, I'll just do one. Ls, dash, l. So dash, l is what we're going to call a flag to ls. And a lot of these commands have flags that you can pass to them. So in this case, dash, l is a flag that tells it to give me a full listing of all the information of these files. So we see here that desktop was modified on July 30 at 12:54. Downloads was modified at September 6. These are the current size and bytes of these directories. You don't have to understand all of this. This stuff on the left, these drwx's, that will become much more relevant later when you have to deal with-- that has to do with who has permissions to look at these files. And so if you weren't the only user on this computer, you would be able to say, OK, I should be the only one allowed to look at this file or I'm going to allow everyone to look at this file. So someone else on my computer can look at this file. I don't even know what this-- what does this do? JOSEPH: I'm not quite sure, actually. ROB: No idea. JOSEPH: But if you don't know, there is a helpful command that you can use to tell you what the output means. And if you type in man before the command-- so M-A-N. ROB: Man. So man is another one that is very useful. And man, ls. So the man pages, they have both commands that you're going to be using at the command line, and they also have functions that will be relevant with C. So you can man-- and I ignored 3. But man 3 printf is going to bring up the C version of printf. But if I just do man printf, this is going to bring up the command printf that happens at the command line. So man, ls. The man pages can be pretty overwhelming. Here, though, you'll see this listing of all of these flags that ls understands. So if we go to dash, l, and-- I'm just going to throw this at you. But in order to search, you want to first hit the question mark or slash button. So slash. And then I can search for whatever I want. So I'm going to slash for dash, l. And there it was. So use a long listing format. That doesn't help me figure out what that particular column meant, but I assume somewhere in here it would explain that. So use the man pages for any command that you don't immediately understand. I'm pretty sure you can even man, man. An interface to the online reference manuals. Oh, one last one that's maybe slightly relevant is ls, dash, a. So notice if I just do ls, I get these five files. If I do ls, dash, a, I get a lot more files. So the thing in common between all these new files is the dot beforehand. So the convention is that a file that begins with a dot is hidden. So you don't want to see that file, you don't want to have it mess with your directory listing. It's only when you explicitly ask, all right, ls, dash, a, show me. The a stands for all files, including hidden ones. So some other commands. Oh, questions at that point? Yes. SPEAKER 3: When you do ls, a, what's the dot, dot? ROB: Oh. So this is what I was talking about. It's the same thing where I can like cd, dot, dot. So technically, dot and dot, dot are files that exist in every single directory where the dot file refers to the current directory. So if I cd, dot, I'm just going to stay in the directory. And dot, dot always refers to the previous directory one level up. So if I go into logs and ls, dash, al, I'll see dot, dot. cd to dot, dot brings me to the previous directory. Yeah. OK. So another pretty important command is rm. So that's what we're going to use to remove. And let me actually do another command first. So mkdir. Mkdir is how you can create directories. And I'll create a temporary directory and go into that temporary directory. And as expected, it's empty. But if I ls, dash, a, I still have dot and dot, dot, because dot refers to the current directory. And dot, dot refers to the previous directory. And those will always exist no matter the directory you are in. And this is a completely unnecessary command, but touch. I'm just using it, because it's an easy way to create files. So touch a, touch b, touch c is just going to create three files called a, b, and c that are completely empty. So the point of me creating those in the first place is just so that rm is how we can remove them. So rm, a. It's going to ask me, remove regular empty file a? And then I'll say Yes. So if I know for sure that I want to erase that file without having to be prompted, remove regular empty file?, then rm, dash, f is going to be the flag that says, force the remove without even prompting me, oh, are you sure you want to delete the file? Yes, I'm sure. So rm , dash, fb will just do it without asking. So let's make some more directories. mkdir, tmp2, cd, tmp2, touch a, touch b. OK. So now I want to remove tmp2 as a directory. So rm tmp2. You cannot remove tmp2, it is a directory. So the issue here is that rm does not immediately work on directories. It's only meant for files like non-directory files. And so what we can do here is rm, dash, r. That stands for recursively, which might not mean anything to you yet. But when you get to recursion, it'll mean more. So rm, dash, r, tmp2 is going to recursively go into that directory. So descend into directory tmp2? Yes, let's go into that. Do we want to remove tmp2/a? Yes. Do we want to remove tmp2/b? Yes. Now do we want to remove the directory tmp2? Yes. And so now the directory and everything inside of it has been removed. There is technically a command rmdir that you can use to remove directories, but it only works on empty directories anyway. And to see that, let's just do mkdir, tmp2 again. Tmp2, touch a. OK. So if I try to remove dirtmp2, it'll say, directory not empty. So I pretty much never use the remove dir command anyway, because rm, dash, r will work on empty directories and non-empty directories. And also, if I don't want to have to go through that whole process of descending into the directory and removing each individual file, rm, dash, rf, tmp2. And now it's gone. Something to be careful about is rm, dash, rf. And it scares me to even type it, because if I accidentally hit Enter or something. So rm, dash, rf, tilde would, without prompting me, the f does not prompt me, it will automatically remove my entire home directory and everything in it. So you may think that's a stupid thing to do. And well, it is. But it can happen very easily by accident if, say, I wanted to remove my slash, vhost directory. And just in quick typing, I accidentally do this. That will remove recursively both my home directory and the vhost directory in this particular directory that just happens to not exist right now. But this would still remove my entire home directory. At least by not having an f, it would prompt me first. And I'd be like, oh, no, I don't want to do that. But people, slash, including me tend to get into the habit of always rf-ing. Even regular files that I can just rm, c, I tend to just rm, dash, rf, c. Just be careful when you're rf-ing. SPEAKER 4: What does C do? ROB: C is I'm talking about that C file in this directory, that rm, c. JOSEPH: And more dangerously, if you use a star, it refers to everything in the directory. So what I commonly tend to do is I will go into a directory and I want to remove all the files in there. So rm, dash, rf, star. ROB: Yeah. Rm, dash, rf, star. JOSEPH: And if you're not careful what directory you're in-- I wasn't in temp, but I was accidentally in my home directory, then I'll remove everything in my home directory. And I've actually done that before, and I think you've done this before or Jay has done that before. ROB: I've accidentally removed-- so ignore that command for a bit. JOSEPH: Not fun. ROB: So in the slash bin directory is a bunch of binary files where there'll be familiar ones like clang. Well, clang and basically all of these things that I'm running at the command line are in this slash bin directory. JOSEPH: Like ls is in here. ROB: So dot, slash, ls would list this directory. JOSEPH: Rm is also in this directory. ROB: I have accidentally rm, rf-ed bin, which removed any command I could possibly ever want. Which then I just reinstall a new Appliance at that point. JOSEPH: So be very careful when you use this command. AUDIENCE: [INAUDIBLE]? ROB: Yes. That's also a bad habit to get into. If you notice, I'm now-- well, you can't notice, but my zoom-in maybe can. So I'm now root@appliance. So jharvard is the user we want you to always be using. Root is the user that has permission to do absolutely anything. So notice when I'm jharvard, if I try to cd-- what's a directory that? Oh, root is a good example. So cd, root. Permission denied. Because if we look at this listing-- and again, you don't have to entirely understand this. But these three dashes are saying that do not let any other user into this directory. And the directory happens to be owned by user root. So the fact that I am jharvard and no one who is not root is allowed into this directory, that means that I'm going to get permission denied when I try to cd into it. So when I am root, I have permission to do absolutely anything, including delete essential files to the Appliance and destroy the entire thing. So it's a bad habit to get into just wandering around your operating system as root. I do it anyway. Questions? And I'll exit root, stay as jharvard. OK. More relevant commands. So going back into our temp, the mv command stands for move. You can move a. Now we want to call it b, so now it's called b. Or maybe we want to move b up one directory. So now this directory's empty. I'll go back to my home directory, and we see that b is in here, because the home directory was one directory up from the directory that b had been in. There's also cp. So cp is copy super section, dot, text. I can call it s, dot, text. Now we have both super section, dot, text; and s, dot, text. This also works on directories. I rf-ed a single file. So cp-- well, first let's try cp, tmp, tmp2. So omitting directory tmp. So similar to rm, the default behavior is to not work on directories. And again, similar to rm, the default behavior-- well, getting it to work with directories is a, dash-r away. So copy recursively the temp directory into tmp2. And so now we have both tmp and tmp2, and that isn't that helpful since tmp was empty in the first place. Tmp2. Now let's copy tmp into tmp2. And we see that tmp2 also has the file a, because the directory and everything inside of that directory was copied. And that can be somewhat helpful if, say you're working on problem set one-- or actually, later problem sets are even more important, because there will be a whole bunch of files and things. But you just want to, for a split second, you're like, all right, I'm going to try something different. Let me just copy my entire pset1 directory into pset1 backup so that if I end up screwing things up, I can go back into my backup directory. There are more appropriate ways of versioning backing up your code, but this is always a quick way to just make sure you have a copy of something that you're about to modify. So echo is also a one-off command that kind of sillily will just print to the command line exactly what you wanted to echo. So echo hi. We'll just print hi. Echo hello world. We'll print hello world. That comes into use when you start combining commands. And again, don't expect you to entirely understand this yet, but it's something to see. And then if you're Googling for examples or you realize you want to do something, it can be helpful. So let's, as an example, so ls, dash, l. So here I see the output of ls, dash, l. And I say, OK, I want to store that into a file. All of this output here, I want to put into a separate file. So this little greater than symbol is what we're going to call. We're redirecting the output into a file. Let's call the file blah, because that's what I tend to always call it. So now we see we have a file blah right here. And if I open it up, I'll see it's exactly the output from the command that I just ran. And similarly, you can-- if this was output to a file, this is get input from a file. What is a command that I-- JOSEPH: I think you can use less or more, probably. ROB: But how about just less blah? I don't know. If you come into this scenario, like there's psets that it's useful for. JOSEPH: You can pipe it into echo. Pipe the file into echo to see it. ROB: It's pipe. JOSEPH: Sorry. ROB: All right. So this is output to a file. This is get the text from the file and hand it over to the program. And you'll also see this guy. So this is kind of doing both at once. And actually, I'll introduce two new commands just to make use of it. History is a handy command that is just going to print out a listing of anything I've ever run a command line. So we see here everything that I have been running this entire time. Lots of ls's. And another useful command is grep that its purpose is to search over text looking for patterns, well, looking for whatever you want it to look for. And so a handy use here is, say we want to grab the history. And I want to look for the commands where I-- what's a useful one to look for? JOSEPH: [INAUDIBLE]? ROB: Or let's just look for all touches, for whatever reason. So this is what it will look like. And you don't have to completely understand that. But the idea is here, history is giving the same output it did here where it's printing out the entire history of everything I've ever run. We are then passing that-- so instead of printing it to the screen, we want to pass that to the command grep which is looking for all instances of the word touch. And so using this combination of the tools history and grep, I can see, OK, here's all of the commands I've ever run, and here's a somewhat common one. We're at the bottom. And it's also giving me the command I just ran that had the word touch in it. But the pipe is a pretty useful thing for combining multiple programs. And actually, it's a shortcut for let me output history to file blah, and let me grep using the file blah as what I want to look over. So the pipe is just a shortcut for those two commands. Yes. SPEAKER 4: [INAUDIBLE]? ROB: Yes. What is-- Oh. Let's test. So cat, dog, fish. So I want to grep. Dash, r, again, is going to be recursively, so I want to descend down all directories. I want to recursively grep for all-- and let me temporarily get this out of the way. Ignore me. OK. So I want to temporarily grep for all instances of the word fish. And so here what I'm doing is grepping recursively for the word fish. And star means over all of these files in this directory. And so it gave me a Permission Denied, because it isn't allowed to read that particular file. But it found fish in the file, test. I could also say, specifically, I only want to look in the file blah, in which case it won't find anything. I only want to look in the file, test. It will find fish. That is a pretty useful command to know in general. There are some alternatives to grep that are supposed to be more programmer friendly, but I tend to still fall back on grep. Questions? OK. Are there other commands? Oh. Just a one-off one that I always find to be fun is cal. So notice when I'm in this lovely full-screen mode, I have no like top toolbar or anything. So cal just gives me a nice little calendar that's right now cut off, I assume. But nice little command. JOSEPH: It is [INAUDIBLE]. Other commands that you might have seen include clang and make. We'll go over them in more detail later. But if you've been working on the PSET, you should be familiar with those. ROB: All right. Questions on command line things? All right. So let's move on to some C-related stuff. Variables math. OK. So just like we had math in Scratch, you can also use math in C. Before we get to that entirely, so variables. Remember that whenever you declare a variable like int x or float y, you have to give it type before the variable name. So types we've seen so far are int, float, double, long long, which I don't actually know if we've seen that so far. There are some other ones. We've see char. There's short, which is like it's the opposite of long long where it's smaller than an integer. We have also seen string. So what is special about string? Why would I say it's not quite like int? SPEAKER 4: It doesn't really exist. ROB: Yeah. So the only reason we have string is because when you do hash, include cs50.h. And we'll see examples of this later-- oh, that does not handle that well-- where cs50.h is doing something along the lines of type def, char star, string. And so that's saying that we don't even know what a char star is yet. But this is saying we want string. Any place you've been using string, you could have been using char star, which actually is a type that exists in the C language. But we'll get to that. Oh, and it goes right back. Neat. So same thing with bool where true and false. That is not really a built-in type in C. Instead, it's just, does this have the value zero? Then we'll just consider it to be false. Does this have the value-- well, does this have any value that isn't zero? Then we'll consider it to be true. So one is true, two is true, anything nonzero is true. So those are those. Questions on declaring variables and variable types and all that? Yeah. SPEAKER 4: For long long, in the book, it said it had to be long long int. But will just long long work? ROB: So these type modifiers. So int x. So we can also say unsigned int x. We can say short int x. We can say long long int x. But pretty much any of those things I just said, unsigned int, short int, long long int, you can get rid of the int and it will just assume that you meant int. So unsigned x, which just means-- you know how normally with an int, you can say x equals negative 3? With an unsigned int, you can't. JOSEPH: And again, for the camera, the question was, what's the difference between long long int and just long long? ROB: Yeah. So I will almost never write long long int. I will write long long. JOSEPH: Any questions? ROB: OK. So silly little reminder of that's how we declare a variable and initialize the variable and declare another variable and initialize it all in one step. So the declaration of the variable and the initialization variable don't have to but can be on the same line. So we have the standard math operators that you're used to-- plus, minus, divide, times. There's also modulo, which we'll see. There is not, at least in C, a built-in power exponentiation caret operator. Well, there is a caret operator, but it's not power. JOSEPH: But it's not exponentiation, yes. ROB: Do not use the caret to assume that it means like squared or whatever. So some things to keep in mind about division. I'll stand. So declared initialize answer. So we're saying float answer equals 1 divided by 10. Print answer to two decimal places. And this is the sort of thing that I would man printf to figure out that what the heck does %, dot, 2f mean? And that just means, well, ignoring the 0.2. And %, f is what we use to print to float. The 0.2 is saying, print that float to two decimal places. So this program has a bug, and you might have seen this before in some prior CS course. But what is that bug? SPEAKER 5: Zero. ROB: Yeah. So when we say, answer equals 1 divided by 10, we want the answer to be 0.1. But 1 divided by 10, 1 is an integer, 10 is an integer. And so when we do an integer divided by an integer, we're going to get back an integer. So 1 divided by 10 is 0.1. Since it needs to give us an integer, it's just going to throw away that decimal place and say that the answer is 0. And so when we print answer here, it's going to print 0.00. JOSEPH: And just as a note, it actually throws away what's after the decimal point. So if you instead had 6 divided by 10, you might think that it would give you 0.6 and then you would round up to 1. But actually, what happens when it type tasks it is that it drops what is after the decimal point. So 0.6 does become 0. ROB: Yeah. And we'll say truncate for that. So whenever you cast to an int, the decimal is truncated. So the fix for that-- there's actually two. And I'm going to do that second, because this one is a much easier fix. So one fix is use floats in the division. And really, you only have to make one of them a float. But it's somewhat clearer just to make both of them floats. So 1.0 divided by 10.0 is dividing two floats. So the answer will end up being a float, and so you will correctly print 0.10 here. Something that doesn't work so well about that is, well, sure, it was easy enough to convert 1 to a float by making it 1.0. But what if instead we had two integers like int x equals 1 and int y equals 10, and then we wanted to do x divided by y? So it isn't easy to just do x.0 or something. So the fix to that is casting. So casting is a way in C to convert from one variable type to another. So here, 1 is an integer. And by putting this float in front of it, we are casting 1 to a float. And so this will convert the 1 to a 1.0. And this will convert the 10 to a 10.0. And then things behave similarly to the previous version we just showed where, as expected, we get 0.10 and it'll print that. And we can do this with variables, too. So we can say, float x divided by float y. JOSEPH: Any questions? ROB: So just like in regular math, we have operator precedence. So in math class, you're more likely to call it order of operations. Here, the official term is operator precedence. But the operator precedence, or most operators, is as you would expect. So just like in math, 2 times 10 is going to be grouped more closely than this 10 divided by 2 and then 2. The order of operations, it will do 2 times 10, 10 divided by 2, and then it'll do 20 plus 5 plus 2. So it's as expected, and you can use parentheses to group expressions. You cannot use square brackets to group expressions. Yeah? SPEAKER 5: Could you actually just go back one second? Can you cast an int to a string? ROB: So in C, you can cast anything you want to anything you want. That doesn't mean it's a good thing to do. So when you cast an int to a string, that means-- and we'll get into this much more thoroughly-- JOSEPH: Much later. ROB: I didn't want to say much later, so I tried to change my sentence. We'll get into it much more thoroughly later where really when you have a string variable-- so a string can be arbitrarily long, right? And we've been saying that an int is four bytes and long long is eight bytes and a float is four bytes. So a string, just like an int, only has a certain number of bytes to it. And that will be four bytes. But a string can be pretty arbitrarily long, right? So hello world already, if that's 10 characters or whatever, that's already going to be over the 4 bytes I can fit into a string. And so how strings really work is that they are where in memory that string is being kept. And so over here, when I say string x equals hello world, inside of x is just saying, oh, hello world is stored at this particular place in memory. So if we try to cast an integer to a string, then we're trying to interpret some random part of memory as a string. And that almost always breaks things. JOSEPH: But if that confuses you, we'll be covering it more in depth later. ROB: Yeah. This is where you're going to get into pointers. And that is a significant chunk of two weeks of this course. SPEAKER 6: Does it work like objects in other languages or not really? ROB: So in other languages, objects would be represented using pointers. It's not the same thing, though. Any thoughts? JOSEPH: No. No thoughts. ROB: OK. JOSEPH: Next. ROB: Just go with that. All right. So modulo. Just like we have plus, minus, divide, and multiply. So modulo is one you may not have seen before. And it just says, give me the remainder of. So 55 % 10. The remainder of doing 55 divided by 10 would be 5. So 55 % 10 is 5. And 3 % 5 would be 3. 8 % 8 will be 0. 16 % 15 will be 1. JOSEPH: One thing to note with this, too, is it might not work as expected if you use a negative number. So negative 5 % 4, some people might think that is-- what would you think negative 5 % 4 would be? SPEAKER 5: One. JOSEPH: So some people say one, some people say negative one. But what-- ROB: I wouldn't even have said one of those. JOSEPH: Two, sorry. Some people say-- ROB: Three. JOSEPH: Three? ROB: Negative-- what was the-- negative five-- JOSEPH: Three, three, three. Sorry. Because modulo, generally, when you've seen it elsewhere, it usually means return a positive number, right? ROB: So when we say in math, % 10's, they tend to want to give you-- if we mod by 10, then we expect to get a number between 0 and 9. In here, that is not the case that you will get negative numbers returned. JOSEPH: So negative 5 % 4 would be negative 1. ROB: But it's rare that you're mod-ing negative numbers to begin with. Skip this. JOSEPH: Yeah. ROB: Meh. OK. So one last thing to point out about floats is it's a dangerous behavior, but floats are not an exact representation. So going back to bytes again, remember that an int is always four bytes and a float is always four bytes. So Lucas's example is pretty good. So think of 1 divided by 3. So 0.3333333. If I only have 32 bits, how can I store 0.33333 exactly? And maybe, for whatever reason, you say, all right, well, let's just say that this particular 1011001, let's just say that should be 0.333333. Well, you only have a finite number of those bits, so it's impossible to represent every single floating point value given just 32 bits. Well, it's impossible to represent any floating point value given infinite-- well, given any finite number of bits. So the issue here is, well, when we used to print to two decimal places, we did correctly get the answer 0.10. But underneath the hood, it's really being stored as close as possible to 0.10 as those bits can represent. Is this on the next slide? Or is it not? JOSEPH: Yeah, it's that. ROB: Blegh, blegh. JOSEPH: Yeah, you can just pull the notes up a bit. ROB: I'm just going to zoom in on the last on that. Oh my gosh, that's [INAUDIBLE]. So that number. That is what will be printed if we run that program. And notice that's not really a big deal if we're only caring about like two to three decimal places. Like we only originally printed 0.10, and that's why we saw nothing wrong. But once we start getting into the exact, exact number that it's representing, we see that it can't exactly represent 0.1. And part of the problem here is like, all right, that's fine, but, well, first, what if we tried to do, answer equals equals 0.1? Is that going to return true or false? And so it's hard to say. I think it actually might return true. Will it first-- I don't know. The answer is once you start dealing with floating point values, you pretty much should not be using equality because of this imprecision. And for all you know, it's the hundredth decimal place that the floating point was not able to correctly handle. And so equality will just fail even though the number-- if you had been using exact numbers, the numbers should have been exactly the same. It's over the course of like 50 calculations using these floating point values, the error can build up and up and up, and things just get wrong. JOSEPH: And there have been really famous examples of this happening. Like NASA engineers have gotten this wrong, causing rockets to explode in the air after they've been launched. And lots of issues like that. So yeah. SPEAKER 6: When you say 0.3 f, does it truncate the rest? Or does it round up or down? ROB: Will printf round it? JOSEPH: I think printf truncates. ROB: OK. So we can similarly go in the opposite direction of this where, in this case, the closest it could represent 0.1 was with this number. The closest it might be able to represent 0.2 is in the opposite direction, 0.199999996356 or something. So if we went in that direction of things, then printf 0.3 f would return 1.99 instead of 2.00. JOSEPH: And I'm not entirely sure on that. You might want to write a small, little program to just check that. ROB: Though, what we are sure of is that if you tried to cast that to an int, and casting to an int is going to cause it to truncate the decimal, if you try to cast 1.9999999 to an int, you'll get 1. And so you should generally use the round function in the math library. Questions? OK. JOSEPH: So moving on to conditions and Boolean expressions. So you have seen these before. And actually, let me make sure my computer's in the right format here. Space. Sorry, we're going to have to deal a little bit with cutoff at the edges. But yeah, you guys have seen this before in Scratch. So this right here is an expression which is used in a conditional statement. So answer greater than zero will tell you true or false. And these are really important, because they allow us to introduce logic into our code. So for example, this is a program written in Scratch that asks the user for an integer and tells them whether the integer that they gave you was a positive or negative number. And the conversion over here to see is you first print out the statement, give me an integer. And then you ask them for an integer. And then you use conditional logic over here to check whether that number was actually greater than zero or not. So here we have a Boolean expression inside of a conditional If statement. Is there any questions? Are there any questions about that? OK. So there's more than just greater than, of course. You can construct Boolean expressions using most of the sorts of things you would think of in math. So greater than. That should be a less than. Sorry. And the spacing. ROB: God forbid you leave it. JOSEPH: All right. So greater than, less than, greater than, or equal to, less than, or equal to. We use double equals to check for equality, because single equals means assignment, right? Yes. And then we can also do not equals by using exclamation mark, equals. And this exclamation mark symbol can also be extended so that if you want to invert any sort of Boolean expression, you can do that. So this will evaluate to true only if the answer is less than or equal to zero. Any questions on that? OK. So you can also combine these expressions using logical And and logical Or. So this is just the And symbol, which should be Shift, 7. And this is the pipe symbol, which is not a lower case L. It's the one that's right above your Enter key. So you use two of these to symbolize logical And the logical Or. So this will only return true if answer is one, two, three, or four. And this will only return true if answer is beyond that on either side. So it's not one, two, three, or four. And the way you would use that in an expression-- ROB: Or a zero or a five. JOSEPH: Zero or a five. Sorry. Yes, yes, yes. OK. And over here now, the same way you would use that expression, a smaller expression side of an If conditional statement, you would also use it the same way by just putting it inside of the parentheses of the If statement. So this printf will only fire if answer is one, two, three, or four. Any questions on combining expressions? So there's another conditional construct we call an If/Else. So basically, this now means, OK, If something I wanted to check was not true, then go to the Else and perform that other action. So in this particular case, I asked the user for an integer. Is the integer greater than zero? Yes? Well, then they picked a positive number. If not, then it must have been negative or a zero. So you picked a negative number or a zero in this case. Yes. Or a zero. And then we also have If/Else, If and Else. So this lets us execute a sequence of things only if the first ones fail. So in this case, now we're making the last one you pick zero. So if they neither picked a positive nor a negative number, then they must have picked zero. So it just goes down the chain like this. So an example of how an If is different from-- an If/Else is different from just a sequence of Ifs. And this is a common question that people ask is, well, if you get like a 95 in CS50, what will this program tell you? SPEAKER 5: You got an A. JOSEPH: Yes. You got every single one of those right. You got an A, you got a B, you got a C and a D, right? So all of these get evaluated in order. So while a 95 is greater than 90, it's also greater than 80, it's also greater than 70, and it's also greater than 60. So you got all of those grades. And I assume you would only want the A. The way to fix that is to replace those with Else/If's. So in this scenario, it sees that 95 is greater than 90, and then it does not evaluate the rest of the statements. Any questions about that? So there's another conditional sort of structure that we have here which we call a switch statement. So this allows you to basically check what the value of a number you put into the switch statement is. So in this scenario, we're switching on n, and we're saying, oh, if n is one, then print that statement. And then break, which means exit out of the switch statement. If it wasn't one, then, well, just eventually check all of those cases. And so it checks if it's one or two or three, and it prints accordingly. And what this default keyword down here means is if they didn't enter any of those, then say Invalid. So let's say I ask for n and the user gives me four. Well, it matches none of those cases, so it will print out what's in the default section. Yes, question? SPEAKER 5: Can you use Boolean expressions instead of one, two, or three? JOSEPH: So the question is can you use Boolean expressions instead of one, two, and three? And in C, I believe you cannot do that. But in other languages, which you might encounter at the end of the semester like JavaScript, you can. Well, you would have to compute first that value and then use it in the switch statement. Yeah? ROB: So part of the benefit of switch statements is think of if you did this as an If/Else, so like if n equals equals one or whatever. Else/If n equals equals two, whatever. Else/If n equals equals three. So the way the program would run is it would sequentially go down that list and check, is n one? Nope. Is n two? Nope. Is n three? Yeah. Do this. Whereas with switch statements, it's actually able to compile it to be really fast. And as soon as it says switch, it says, all right, n is two, I am immediately going to jump to where I am supposed to start executing. I'm not going to first check, is n one, is n two? It can immediately start doing what it's supposed to do. And because of that, it can't take Boolean conditions. Or else it would have to do the sequential, like, all right, is n greater than zero? Else is n greater than 10 or whatever. JOSEPH: In this case, if you used If/Else, If's, then the switch would run approximately three times faster than the If/Else, If. We can organize the switch in such a way that we don't break after each of the cases. So in this case, I'm partitioning the numbers that we choose into one and two being not high numbers and three being a high number. So in this case, if n is one or two, it will hit the case and then it will fall through, because there is no break. And it will end up here. So if we pick one, it will do the printf and then break so that none of this is executed. And of course, if they enter in three or something else, then it will skip those and not go there, and it will execute instead the corresponding line. Are there any questions about that? Yes? SPEAKER 4: Would you get an error if you had a break after case one but it didn't have something for it to do? JOSEPH: So the question is would you get an error if you have a break after case one but there's nothing to do? And the answer is no. You won't actually get an error. Yeah, mm hmm. So as sort of a little change here, I'm going to put a printf here. Whoops. So what would this print if I put one in as input? Yeah. It would tell you it didn't take a high number twice, right? Because it would hit that first case, it wouldn't break, and it would fall through to the second case. Any questions about that? ROB: Did you have another question? JOSEPH: OK, cool. All right. So there is something else we call a ternary operator which is basically an alternate syntax to doing If and then Else. And it lets you do it all on one line. So in this particular program, I'm asking the user for n. And if n is greater than 100, I tell them they picked a high number. Else I tell them they picked a low number. So we can use this really long syntax, string, S, and then check if n is greater than 100 and assign it accordingly. But we can make this much more concise by using this ternary operator syntax which involves a question mark and a colon. So the question mark is essentially asking a question, right? ROB: Maybe zoom in on that. JOSEPH: Yes. Good point. So this is the ternary operator. I first ask the question, is n greater than 100? If it is, then I execute the first part before the colon. If it's not, then I execute the second part after the colon. So if n is greater than 100, then it picks high and puts that into string s. If n is less than 100, it picks low and then puts that into string s. So that will condense this big chunk down into just that one line. SPEAKER 5: Is that popular? JOSEPH: Yes, it is quite popular for things where essentially you want to do an assignment based on some sort of condition. And in this case, we were trying to assign a value to string s. It's not so-- I guess I don't really prefer it in other cases. But it's especially useful for this assignment. ROB: That is a pretty common pattern where you have some variable that you're going to say, if something, set this variable to one value; else, set this variable to another value. And that is the scenario where use a ternary. JOSEPH: And you're saving lots of lines, right? And it just makes your code arguably a little bit more readable. Yes, question? SPEAKER 6: For a ternary, could you go, string s equals s, question mark? And then you could have, say, five different options. And depending on what the number of n was, would you choose one of those? JOSEPH: So the question is, is there a sort of syntax where you can do string s equals n, and then have more than two options after that question mark? And a simple answer is no, there's not really a good way to do that unless you want to nest multiple ternary operators inside of each other. You could do like n greater than 100, question mark, and then another ternary operator, n greater than 50, question mark, and nest it that way. But in that scenario, your code's getting kind of unreadable and messy, and it might be better to just go to an If/Else statement at that point. ROB: And also, as a side note, PHP incorrectly implements the ternary operator such that nested ternaries don't even work as they should. JOSEPH: Yeah. So it gets a little bit confusing, especially when you go to different languages. ROB: It's confusing enough that languages are wrong about it. JOSEPH: So actually, just to clarify, does everyone know what that %s does over here? Any questions about that? I guess just for the camera, the %s basically lets us put a placeholder for a string. And then at the end, we specify that the variable we want to put into this place holder is s. So that basically takes s and it puts it in here. And then it will print out, you picked a high or you picked a low number. OK. So loops allow you to perform things in circular motions, right? You might have encountered this in Scratch in the form of Forever loops or Repeat Until or Repeat a particular number of times. So why is this good for us? Well, in C, let's say we have this song implemented in Scratch that sings, this is the song that never ends. It just goes on and on and on forever and forever. Well, you can't really make a program that has an infinite number of printf statements in it, right? So in this particular scenario, one way that you could make this work and to make it print forever is to instead use a While loop. So a While loop will execute what's in the body of the two braces that belongs to it based on what the condition is. So in this particular example before, if we want to print this forever, what might we do? Well, sure, right? So this sort of combines the idea of some Boolean expression along with a loop. And we learned about Boolean expressions earlier. So whenever the condition inside of that While remains true, this loop will execute on and on and on. And in this case, if we just supply it with true, this causes an infinite loop which prints the song on and on and on as we desired before without having a program that has an infinite number of printf statements, which is not possible. So more compellingly, though, you can use this with a variable and a condition. So let's say we want to repeat the phrase, totally loopy, 10 times. So what you can do with a While loop is you can first initialize a counter variable outside of the While loop to 10. And then basically, each time you go through the While loop, you print out the statement and then you decrease the counter variable until at the end, at some point, once we subtract I enough times, 1 from I enough times-- and just to clarify, I minus minus means I equals I minus 1. That will basically bring I down to the point where once I hit zero, this condition is no longer true and so it exits out of the loop. So totally loopy only prints 10 times. Any questions about a While loop? OK. So there is a way we can do what we just did in a more concise manner with what we call a For loop. So a For loop consists of an initialization, a condition, and an update, just like we had before in this While loop. So let's take a look. In this While loop, we had an initialization, then we had a condition that we checked. And then we had an update step at the top. With a For loop, this basically takes these three things and condenses it down into one line. So the first thing that it does in the For loop is the initialization. And then you do a semicolon, and then you do the condition, which is I greater than zero goes over there, and then the update step. So this gets performed at the very end of the loop body. So these two programs are essentially equivalent. Any questions? So what is one difference between these two? Can anyone point it out? It might be a bit subtle. It's just a very small difference. Yes? SPEAKER 5: You wouldn't be able to use the I variable outside of the For loop [INAUDIBLE]? JOSEPH: Exactly. So this is something we'll get to later called variable scope. But essentially, this int I lives outside of this While loop. So once this While loop is done executing, I'll be able to use I later on in the program. Whereas with this For loop, this int I is scoped inside of this For loop. And because it is inside of this portion of the For loop, that starts at the parentheses and ends with the curly brace over there. Anything that's declared inside of here cannot be used outside. So if I try to use I outside, it'll tell me, undeclared symbol. And essentially, I wouldn't be able to use it. ROB: And well, 10 years ago, in literally all cases, curly braces are what you used to determine the scope of a variable. So in there, int I equals 10 is declared inside of this set of curly braces. And so then as long as you try to use I before this curly brace, it's fine. You might see when you type make, you see dash, dash, std, equals, c99. So that is a later version of C that GCC has implemented that also gives this shortcut. So this used to not be allowed in C. And you can see why, because this int I is outside of this curly brace but it's still considered to be in the scope of these curly braces. But this is a very convenient thing, and so it is a good extension. JOSEPH: Any questions? OK. So what's more useful is that sometimes you want sort of dynamism in your loop, right? You don't want to just necessarily print totally loopy all the time, you want to count down from 10 or something. And so you can use the counter variable inside of that loop as well. And in this case, this program just counts down from 10 all the way down. And what does it not print? It doesn't print zero, right, because when-- Yes, it also does not print 11. So it does not print zero, because when I is zero, remember, it evaluates the condition before it goes on to execute the loop body. And when I is zero, this is false, so it does not print out counting down zero, it just prints out counting down 10 all the way down to 1. If we actually wanted it to print zero, then we would put an equal sign after this greater than sign. OK. So one way to do input validation, which is when you ask the user to do something, you want to make sure they follow your instructions, is to use the While loop, right? So in this particular case, I'm asking for a positive number and then I'm waiting for input. And then I checked While the input is less than zero, keep asking them. So as long as they give me a number that is not positive, keep asking, keep asking, keep asking. But what is sort of weird about this? Or what doesn't seem optimal about this structure right here? Anyone? Yes? SPEAKER 6: You're repeating the instruction twice. JOSEPH: Right. So we have two printf statements here, right? So there is a way we could get this just down to one that would make our code easier to read and a little bit more clean. And then we wouldn't have to have Get in twice as well. And one way you can do this is by using a Do-While loop. And a Do-While loop is basically a different form of a While loop where whatever is within the curly braces gets executed at least once. So in here, I declare, int input, outside first. And then I just say, do this instruction while input is less than zero. So it hits the Do first. It will always execute this at least once, so it will always ask the user for input at least once. And then it evaluates that input, and it goes on in a circle. Yes, question? SPEAKER 6: Is there a way to do it [INAUDIBLE] types, like if you say, GetString, and somebody [INAUDIBLE] is there a way to [INAUDIBLE] JOSEPH: So the question is, is there a way to do input validation if the user does not put in the right type of variable? So if we ask for an int and they give us a string instead. And in the functions that we implement for you, GetInt, GetString in all of those functions, they actually already do that sort of basic type input validation under the hood. So if you're using the functions that we gave you, you don't really have to. But if you want to look more into how you can actually do that, you can look under the hood at the file I/O-- not file, the standard I/O functions like a reading from standard input and standard output. And you can get a better sense of how you might do that. ROB: One issue, though, is specifically with the example you said, you expect a string and I enter an int. How would you tell the difference between intentionally wanting the string 123 versus wanting the int 123? So string, it's pretty much there's no validation, it's just whatever they entered you will interpret as a string. Int is easier, because no matter the input you take from the user, you are always taking a string. And so that string you can then check, are all of these actually numeric digits? JOSEPH: OK. Any questions about a Do-While loop? ROB: Oh, and this is also-- going back to scope, a somewhat common mistake is trying to use some local variable from within this Do-While loop inside of this condition. And actually, if we just got rid of this and said, int input equals GetInt, then the compiler will yell at us, because input does not exist outside of the scope of these curly braces. JOSEPH: And that's why we need this lineup here. OK. So you can also break out of a loop early if you want to. So this is a different way of implementing what we just implemented. And instead of using the condition within the parentheses, we're using an If statement inside of the body of the Do-While loop. And basically, when the input is finally greater than zero, we will break out of the loop. And so we will go all the way down here. And you can see that this would probably be preferred in this scenario, because it's a little bit cleaner and a little bit easier to read. Whereas this, you sort of have extra lines in it. It's just a little bit uglier, I guess, in a sense. Yes, question? SPEAKER 4: Will break only get you out of one set of braces? JOSEPH: Right. So the question is will break only get you out of one loop? And the answer is yes. So if you have nested For loops, for example, if I have For int I equals 0 until 10 and then For int J equals 0 until 10, if I break out of the inner loop, I will still go to the outer loop. So it'll keep performing the operations on the outside. Any questions about that? Yes? SPEAKER 5: But break only functions for curly braces, not for other statements? [INAUDIBLE] JOSEPH: So the question is will break only function for loops as opposed to other statements like If? And yes, that is the case, because you're breaking out of a loop, right, in a sense. ROB: In the vast majority of cases, it's this is the sort of If something, then break. So you don't have to break to apply to the If that is wrapping around it. And also, this isn't much of a loop, but remember that switches are also broken out of by breaks. We saw breaks being used with switches before. JOSEPH: And you can also use them in While loops and For loops. Any questions? OK. So next up is functions. So you might have used one of these BYOB blocks in your Scratch project. And this basically allows you to define a set of instructions to be followed. And what I mean by that is let's think back to math, right, algebra. You have what we call a function of x, some variable, and let's say this function is f of x equals x plus 5. So you can think of f of x as this black box that takes 15 in and then produces 20. So more generally, a function is something that takes some inputs and then produces some outputs. And why are functions good? They're good for a number of reasons. So does someone want to take a stab at what organization means? In terms of why functions are helpful? Yes? SPEAKER 4: It makes your code more readable. JOSEPH: Right. So one of the things is it makes your code more readable, right? Instead of having like int x equals x times x times x, I can have cube of x, which is more readable and more understandable to a reader. Organization is also in terms of splitting up your code into manageable portions, so that instead of trying to implement this all in one long section in main, you can sort of split it up into like, OK, let's write a function to cube something, let's write a function to square something. That way you can split it up into tiny, little parts that you can tackle as opposed to trying to tackle a big problem all at once. ROB: Or even tiny, little parts that you and a partner can tackle. JOSEPH: Yeah. ROB: So instead of both of you trying to implant one function at the same time. JOSEPH: Simplification. Anyone want to take a guess? Yes? SPEAKER 5: More repetition. JOSEPH: Right. So one thing that you can do with simplification is that it's sort of on the same lines as re-usability is that once I write a cube function, I can just use that over and over and over again in my program instead of typing x times x times x over and over and over again. And simplification here also just means it makes your code sort of easier to debug once you split this up into functions. Because then you can localize where your problems sort of are. Any questions? So another idea is abstraction, right? This black box. Like do you know what GetInt does to receive input from the user? We haven't really told you, right? All we've told you is GetInt does exactly what it says it does. So even if we don't tell you how it works, you still know. So in this particular case, this is a quadruple function which does different things to an input to produce an output. And you can quadruple a number by multiplying it by four. Or you can what we call bit shift it by two. And we'll cover this a little bit later. And there's no need to know how this function actually works as long as it works as stated. So under the hood, I could be like, return input times eight divided by two. And you wouldn't know, right? All you need to know is it does what it says. So that's the useful thing about abstraction. And another thing is sort of this idea of localizing your code to one particular section. So if you do have a problem, you don't have to go all over your code trying to fix where the problem was. So in this case, I implemented cube wrong. I thought cube was multiplying by three. So in this case, this is one program that just has multiplying by three everywhere. And there is another program that has factored cube out into a function. And so now if I want to fix my mistake here, I have to fix every single line of code in this program. Whereas on the other hand, if I use the function, I only need to change what was wrong in one place. So in computer science, we call inputs and outputs. Inputs are called parameters or arguments, and outputs are called return values. And we will see how this helps us sort of define a function in a second. So this is a function definition for cubing. So it takes an input, and then it returns that number times itself three times. So let's break this down. So we have a function header, which basically consists of three things. So we have the parameters, which are, as I said before, the inputs into this function. And then we give the function a name. In this case, it's called cube. And then we specify what the type of the return value is. So in this case, my cube function takes in an integer and it also returns an integer. So if I pass in two, two is an integer, it returns eight to me, which is an integer. So return type name parameters. Questions about that? And then the return value is actually specified at the end by saying return and then returning whatever contains the return value. So in this case, if we put it all together, a function takes in parameters, it's called something, and it returns something that is the type that we say it was going to be. Any questions? So how do we use a function? Well, we write a function and then we use it in our program, right? So I called it cube, and then I can use cube. But what's important to note is that order matters. If I have cube below main, it's going to run into cube. And at this point, there's nothing called cube in the program, and it's just going to be like, I have no idea what cube is. So it will tell you, implicit declaration of function. That's the error that shows up. And so in this case, cube is below main, so it's not going to know about it. SPEAKER 5: So main is usually the last function defined? JOSEPH: So the question is, is main usually the last thing that you'd define? And no. It's because we usually like main to be at the top, right? Because that's the first thing you want the programmer opening the program to see. And so how do we solve this issue of we want main to be at the top, but the functions that we want, we want them to be below main yet be able to use them inside of main? Well, we use what we call a function prototype. So what a function prototype essentially is is it first takes what the signature or the function header of what we want to implement down here, and we put it at the top of a program. So in this case, we say that, well, later on in our program, we're going to make a promise to implement this function called int cube, which takes an integer input. So now, because that is above main, main, it's going to say, oh, well, later in the program, that's going to be there so I can refer to it, so I'll just let it go through for now. And then at the bottom, we implement cube. And then main will just say, well, it will sort of link these two symbols together. And we'll cover what that means later on. And so it'll know that this is the cube function that it should use. ROB: The [INAUDIBLE] about wanting main at the bottom or top, I've seen both. There are things that just like to put main at the bottom. But once a project gets particularly big, usually main is in a file all its own. And at that point, like the int cube line would-- inside of stdio.h are a bunch of lines just like that int cube int input line. And so those prototypes are things you tend to put into header files, at which point, it doesn't matter. Well, it doesn't matter. Those always go at the top. And if main isn't a file all its own, you don't have to worry about putting individual function prototypes in the file. JOSEPH: And we'll get to that a little bit later when Rob starts talking about compiling. And so there's also a difference between parameter and argument. And parameter is just what we call these inputs when we define the function. And we call it an argument when we actually pass it into the function. So in this case, this is a parameter, as we said before. And when we actually use it over there, cube of x, then x itself is what we call an argument to the function cube. ROB: So parameter's arguments are-- there is this distinction, very confused interchangeably. At this point, to me, it's like one of those words that when I see it out in the wild, I can't help but immediately question whether they are using it in the correct context, because the difference is subtle enough that just everyone tends-- I almost always say argument regardless of what I mean. JOSEPH: And functions are also useful for what we call side effects. So a function can take no inputs, and it can also produce no outputs. So in this particular case, I am defining a subroutine that has no return value. And in order to specify that, we use what we call a void over here. And so the side effect of this function is that it just prints stuff out to the page. It doesn't actually take any inputs, and it doesn't actually produce any outputs. But this could be useful in the sense if you want to, for example, debug something in your program, if you want to write a little subroutine that prints out, let's say, the contents of memory or something. And so these side effects are sometimes useful outside the context of just like inputs and outputs. Any questions? And to end this particular segment, what does this program do? I'll give you guys a couple of seconds to read through it. At a very basic level, what we want to say is that it swaps x and y, right? So how many of you actually think this will swap x and y? Raise your hand. No one. OK. Who thinks that it will not swap x and y? And the sum of that was not the entire room. So some people are not sure. OK. That's reasonable. So let's go through what happens when you actually call functions first in order to answer this question. So this is what memory sort of looks like. This is sort of like a simplified model of what memory looks like when you run a program. So there's something called the stack down here and something called the heap. And these grow towards the middle of memory. So in this particular case, when you call a function, it gets put on the stack. And then whatever is contained in that function stays in what we call that function's stack frame. And so to get a nice visualization of this, let's-- for example, we had the program main earlier. And inside of main, we called cube. So main would first go on the stack frame, because it's the first function that's called. And then when cube is called inside of main, it gets put on top of main inside of memory. So what you'll notice here is that cube has its own parameters and its own locals. So when you actually pass something to a function, the parameters that it gets are copies of what was passed in from main. And to sort of explain this, let's walk through a program. So we have the stack; this is just the stack portion. And what we do is we first initialize x and y to one and two. So we have these little boxes. They're sitting in main's stack frame on the stack. They contain one and two. Now we call swap. What happens is we pass x and y into swap, and swap creates its own copies of those variables to use inside of its stack frame. So now over there, we have a, which contains the value that x had; and b, which contains the value that y had. So one, two. And you'll notice that this is separate from x and y inside of main. So we now create a temporary variable to contain a. We set a equal to b, so it changes from one to two. And then we set b equal to temp, which is one. And then now we exit out of this function. When you exit out of the function, the stack frame gets popped off the stack. We call it push. You push a stack frame onto the stack and you pop if off the stack. And so what happens is everything that was in that stack frame sort of just goes up in flames. And so that no longer exists. But what do we notice? We never actually changed the values of x and y, right? So those stayed local to main. And by passing things into swap, we actually never changed those values. And what do we call this? We call this passing by value. So in C, when you pass things into functions, it passes them by value and makes a copy of them for the function to use. And we'll learn about something called passing by reference later, but that's a way you can solve this problem. But we won't worry about that until later. ROB: And actually, that term, passing by reference, so C doesn't even have passing by referencing. C exclusively has passing by value. No matter what you do, you are always passing a copy of something. It's just that, like I sort of mentioned that before with pointers and that a string is really just four bytes pointing to someplace in memory. Well, if I have this string and it's telling me that is where the string-- well, if I have this pointer to this place in memory, then I can pass a copy of that pointer to a function, and that function still knows where in memory it is. So both of these pointers are pointing to the same place in memory, and that's how we're going to be able to modify things beyond the current stack frame. JOSEPH: Do you want to do compiling? ROB: No, it's 5:30. JOSEPH: OK. It is 5:30. OK. So we will cover compiling I guess in the next section, or your section leader will at that point. And-- ROB: Any questions? JOSEPH: Any questions? Yes? SPEAKER 5: Using strings from CS50, any functions that we want to use for those, that'll be like C functions. CS50 hasn't gone in and made any additional. ROB: Correct. Any of the C like [INAUDIBLE], you would use those on our strings. JOSEPH: And one last thing I want to mention is that we have a style guide for this class. ROB: Oh, yeah. JOSEPH: So if you've come from a programming background before, you might have certain conventions when you're writing code like putting braces on the same line or particular ways of indenting or naming your variables. In this class, we want to follow a specific style guide just because, well, if you go out and work in industry, you're going to be expected to follow the style guide of the company at which you go to. Like for example, Facebook I think has a particular sort of naming convention. And there's differences between camel casing variables and just like separating them with underscores. And also, I think most importantly, like for example, indentation, right? We do curly braces start where the condition is, and they are on the next line. And we also put curly braces in even if it's only one line. And a lot of times, there are ways to do it where you can leave these braces off if it's only one line under the If statement. But in this class, we want to follow a specific style guide just so you get used to that sort of thing. ROB: Yeah, and Style 50 is going to enforce this style guide, and we're going to use Style 50 to grade your code. So it makes things easier for us and hopefully shouldn't make things that much worse for you given the standardized style shouldn't be that unrealistic. JOSEPH: And finally, to find the style guide, go to manual.cs50.net/style. And yeah. SPEAKER 4: Are you going to enforce any characters per line? ROB: Yes. JOSEPH: Sorry, guys. ROB: That's like one of the only ones. At this point, I am OK with 120. I'm OK with saying 120 characters per line. I understand there being some limit. I think 80 is so small, but we're enforcing it. JOSEPH: Personally, I think with C, 80 characters is more OK. Once you start getting to other languages like JavaScript and PHP, not so reasonable to just limit it to 80 characters. OK. Well, that was the super section. Does anyone want candy? SPEAKER 4: Yes.