[MUSIC PLAYING] ROB BODEN: All right. So, first thing first, of video from a familiar face. [VIDEO PLAYBACK] -All right. This is CS50, and this is the start of week three. I'm sorry I couldn't be there with you today, but allow me to introduce CS50's own Rob Boden. [END VIDEO PLAYBACK] [APPLAUSE AND CHEERS] ROB BODEN: The filmography in that video is fantastic. All right. So first, there's another lunch. It's tomorrow at 1:15. There's no lunch this Friday. It is with Quora. And Tommy's not here yet, but one of the people there is former head CF, Tommy McWilliam. So he's a fun guy. You should come. All right. So last week, we started breaking apart about what a string really is. We've known since the beginning that it's a sequence of characters. But last week, we delved into the fact that what is really a sequence of characters, well, we now have arrays of characters. And we know that a string, it's an array of characters, at the very end, we have this special null byte, this backslash 0, that indicates the end of the string. And so a string is an array of characters, but we can have more than just an array of characters, we can have an array of any type of thing we want. So, if you recall from last week, the Ages program that David introduced really quickly. So first thing we're going to do is ask the user for an integer, the number of people in the room. Once we have that integer, we're declaring an array. Notice this bracket syntax. You're going to get used to that. So we're declaring an array of integers called ages, and there are n integers in this array. So this pattern right here, this 4 int i equals 0, i is less than n, i plus plus, that is also going to be a pattern that you get very used to. Because that's pretty much how you're always going to iterate over arrays. So remember that n is the length of our array. And so here, we are repeatedly asking for the age of person i in the room. After this, we go down, and for whatever arbitrary reason, we then print out how old they're going to be a year from now. And running that program, let's make ages, dot slash ages. So number of people in the room, let's say there are three. And say, the first person is 13, next is 26, and the last is 30. So then it'll iterate over those three people, print out 14, 27, and 31. So remember that when we declare an array of size n, the indices in that array, the array has values and indices 0, 1, 2, all the way up to n minus 1. So when we said there were three people in the room, and we put in here the first iteration through this loop, i is going to be 0. So in index 0. We are assigning the first age the user enters. Then in the next one, we're entering the second n the user enters, and in next to two, the last n. So notice that an array of size three does not have anything in the index three. This is not valid. All right. So, going back here. So now that we've dealt with arrays, we have some familiarity. Now we're going to move on to command line arguments, which are going to be pretty relevant to this problem set. So up until now, whenever you've declared your main function, we've said int main void. So void just means that we aren't passing any arguments to this function. Now we're going to see that main can take some arguments. Here we call them int argc and string argv brackets. The brackets, once again, indicating that we're dealing with arrays. So here, string argv brackets, we're dealing with an array of strings. So argc, that's going to indicate how many arguments we've passed to this program. And to see what that means, let's close this. OK. So up until now, we've run every program like dot slash ages. We can also, at the command line, past pass arguments, thus the term, command line arguments. So the first argument, hello world. So here, argc would be three. It's the count of the arguments at the command line. Argc is always at least 1, since dot slash ages, itself, counts as one of the command line arguments. Then hello is the first. If dot slash ages is the zeroth, then hello is the first, and world is the second command line argument. So the string argv, we're going to see, contains the strings, dot slash ages, hello, and world. And, by David's request, we're going to play a video introducing that. [VIDEO PLAYBACK] -Up until now in programs we've written, we've declare main as int main void. And all this time, that void has simply been specifying that the program does not take any command line arguments. In other words, when a user runs a program, he or she can provide command line arguments by writing additional words or phrases after the program's name at the prompt. Well, if you do you want your program to take command line arguments, one or more such words, we need to replace void with a couple of arguments. So let's do that. Include CS50.h. Include standard io.h. Int main. And now, instead of void, I'm going to specify an int called argc, and an array of strings called argv. Now, argc and argv are simply conventions. We could have called these arguments most anything we want. But what is important is that argc is an int because, by definition, it is going to contain the argument count, the number of words in total that the user has typed at his or her prompt. argv, meanwhile, argument vector, is going to actually be an array storing all of the words that the user has typed at his or her prompt. Let's proceed to do something now with one or more of these command line arguments. In particular, let's go ahead and print whatever word the user types after the program's name at the prompt. Open bracket. Close bracket. Printf percent s backslash and comma. And now I need to tell printf what value to plug into that placeholder. I want the first word that the user has typed after the program's name, and so I'm going to specify argv bracket 1, close parenthesis, semicolon. Now, why bracket 1 and not bracket 0? Well, it turns out, automatically stored in argv 0 is going to be the program's actual name. So the first word that the user types after the program's name is, by convention, going to be stored in argv 1. Let's now compile and run this program. Make argv 0, dot slash argv 0. And now a word like hello. Enter. And there we have it, hello. [END VIDEO PLAYBACK] ROB BODEN: All right. Close that. So taking a look at that program that we just introduced to us, well, just to show, if we print argv 0, make, now what is it, argv 0, dot slash argv 0. So, as expected, it's printing out the name of the program, since argv 0 is always going to be the name of the program. But let's do something a bit more interesting. So in the problem set, you'll be introduced to this function, atoi. So what do we use atoi for? That's going to convert a string to an integer. So if I pass the string, one two three, to atoi, that'll convert that to the integer, one two three. So we're going to convert the first command line argument to an integer, and then just print that integer. So basically, we're kind of reimplementing getint, just the integer is entered at the command line instead of in the program interactively. So then, making argv 0, let's do it in here, and close that. So running argv 0, and let's enter the integer, one two three four one two. So it'll print the integer, one two three four one two. There are some subtleties to atoi that it'll stop caring about anything beyond a valid numeric character, but that doesn't matter. So what do you think happens if I do this? Segmentation fault. So why is that? If you look back at our program, we're converting argv 1, the first argument after the program name, to an integer. But there is no argument passed after the program name. So here, we see that this is a buggy program, since, if we try to run it without any arguments, it will just crash. So another common pattern you'll see is something like, if argc is less than two, indicating that there was not at least the program name and a first argument, then we'll do something like printf, not enough command line arguments. That's probably not a good one to print, it's probably something, like you should enter an integer at the command line. I'll just end it there. And then return 1. So remember that at the end of our program, if we return 0, that sort of indicates success. And main also automatically returns 0 if you don't. So here, we're retuning 1 to indicate that that's not success. And you can return whatever you want, just, 0 indicates success, and anything else indicates failure. So let's run this version of things. So now, if we don't enter a command line argument, it'll correctly tell us, not enough command line. Didn't finish the sentence. Else, if we actually pass it one, it can complete the program. So this is how you would use argc in order to validate the number of command line arguments that are actually passed. So let's make this program a bit more complicated, and look at the second iteration of things. So now, we're not just printing the first command line argument. Here, we're iterating from int i equals 0, i is less than argc, i plus plus, and printing argv, index i. So this pattern, again, this is the same pattern as before, except instead of calling the variable n, we're using argc. So this is iterating over each index in the array, and printing each element in that array. And so, when we run this program, well, I didn't enter any command line arguments, so it just prints the program name. If I enter a bunch of things, it'll print one, each on its own line. OK. So let's take this one step further. And instead of printing each argument on its own line, let's print each character of each argument on its own line. So remember that argv is an array of strings. So what is a string, but an array of characters? So that means that argv is really an array of an array of characters. So taking advantage of that, let's ignore this for now. Let's just consider the string argv 0. So if we want to bring each character of argv 0 on its own line, then I want to do the pattern we're used to, i is less than the length of the array, which here, is strlen of, that's not what I want to do, string s equals argv 0. So i is less than the length of our array, which in this case is an array of characters, i plus plus. And so, as we saw last week, it's ideal if we move that strlen outside of the condition, since n will be adding the strlen of s each time we go through the loop, and it's not going to be changing. So we'll set it equal to n over here. OK. So now, we're iterating over each index in the array. And so, if we want to print each character in that array, percent c is the flag we want to use for characters. And now a bracket i is going to be the string, index character i, so if the string were hello. then s 0 is going to be h, s bracket 1 will be e, and so on. So now we want to combine these two things. We want to print each character of each command line argument. So we're going to have a nested for loop. And conventionally, the first counter is i, the next is going to be j, n will be the strlen of argv i, i is less than n, i plus plus. And now instead of printing argv i, so argv bracket i is going to index-- that's going to be the i-th command line argument, argv i, j is going to be the jth character of the i-th argument. I'll get rid of this up here now since we put it into that loop. So is equivalent to string s equals argv i, and then s bracket j. Well, we don't need to declare this variable s. Instead, we'll just combine these two into what we had, argv i, j. SPEAKER 1: [INAUDIBLE]. ROB BODEN: Good call. So this is broken. If I actually ran it, we would have realized this. So the counter I care about in this particular for loop is j, the iterator. So you would have run into issues, probably an infinite loop, if we hadn't fixed that. That's why we're also talking about debugging today. OK. So let's run this program. And let's actually add a separate printf right here that will just print another line, since this means when we run the program, there'll be a blank line in between each character of each command line argument. Well, we'll see what that means. Oop. Got some bug. Error implicitly declaring library function strlen. So going back into our program, I forgot to hash include string.h. So string.h is going to be the header file that declares the function strlen. OK, it compiles. Now, let's run it. So just that. It's going to print out our program name, hello world. It's going to print each thing, each character, on its own line. OK. So let's actually take this one step further. And instead of using string.h, let's think about how we'd implement our own strlen function. So I'll immediately give a function signature. So let's call in my_strlen, and it's going to take a string as an argument, and we expect to return the length of that string. So, where's that guy? Yes. OK. So remember from the earlier slide that was also from last week, that an array of characters, well, a string, so let's say this is our string s. So if s is the string, hello, then, H-E-L-L-O, in memory, that's going to be, and then this backslash 0 character. So how do we get the length of s? Well, the trick is looking for this backlash 0 character, this null terminator. So the algorithm Is going to be something like few enough characters that-- let's have this hand represent some counter, let's call this int length. So, starting from over here, we're going to iterate over our string. So the first character, it's H, and it's not back slash 0, so the length is 1. Iterate to the next character, E, and it's not backslash 0. Length is 2. L, 3. L, 4. O, 5. And finally, we reach backslash 0, and so that means, well, this string is over. So let's return 5. So actually implementing that, first, my n length equals 0, my right hand. And we're going to iterate-- SPEAKER 1: [INAUDIBLE] ROB BODEN: Oh, shoot. Good call. Boom. So n length equals 0. So now, while s length does not equal and then, backslash 0. So remember, this backslash 0, it is an actual character, and it indicates the end of the string. Just like, also, backslash n is an actual character. Backslash 0 is going to indicate the end of our string. I don't want to put that there. And while s indexed by length is not equal to the null terminator, then we're just going to increment length. So then, at the end of our program, length is eventually going to be 5 in this case. And we'll just return length. OK. So now down here, I don't do my_strlen. Let's compile it to make sure everything runs smoothly. Was I doing in 2? Or was that 1? That should do. All right. So this is argv 2. Works as anticipated, although was that the one I did it in? Yes. OK. This version of things did not have the printf new line after, but it doesn't make any difference. OK. So worked as expected. Now we can even combine this one step further, where notice here, well, first, we're grabbing the strlen of argv i, and then we're iterating over each character in that string. So instead of doing that, what if we just combine this logic of waiting until we hit backslash 0 right into this for loop? So iterate while argv i, j does not equal backslash 0. So let's run it first. All right. So here, this condition is saying-- let's clear that. So now, let this be our argv. So when I just ran that program before, argv is an array of strings. And so, if I run it with dot slash argv 2, hello world, then the argv itself is length 3, for argv zero, hello, and world. And inside of each of these indices is, itself an array, where this'll be dot, this will be slash, I don't know if that was the right direction, I don't think it was. A-R-V dash, need more space. Let's cut into this array. A-R-V dash 0, and then backslash 0. And then in disarray will be hello. Let's say, H-E backslash 0. And finally, W-O backslash 0. So the algorithm that we just wrote, the nested for loops, what they're doing is, we first have the counter i and then j. This would be easier with code on the screen, Let's go back to this. OK. So notice that i is the iterator that's iterating over each command line argument. And j is the iterator iterating over each character in that command line argument. So what this innermost printf is doing is, we have printf argv 0 0, printf argv 0 1, printf argv 0 2, 0 3, 0 4, 0 5, 0 6, but now, argv 0 7 is going to equal backslash 0. So then we exit that for loop, and now i iterates to 1. And now we're going to print argv 1 0, argv 1 1-- well, now, since I cut hello short, argv 1 2 is again going to be backslash 0. And so, increment i and continue, and so on, until we print out all of world, and those are three command line arguments, and we'll exit out of the outermost loop, and finish our program. OK. So let's come back here. So you'll gain some familiarity with command line arguments on this particular problem set. Now, debugging. So you probably have already had to do some debugging with your previous problem set. And one very easy way of debugging, first, let's look at a buggy program. Well, walking through this program, we're going to ask the user for an integer, grab that integer, and then, arbitrarily, we have a while loop that is just going to decrement i until it's equal to 10. Let's just assume I'm entering an integer greater than 10. So decrement i until it's equal to 10. And then we have another while loop that, while i does not equal 0, we're going to decrement i by 3. So if you see the intent of the bug here, it's that this'll decrement i to be 10, and then this while loop will decrement i from 10, to 7, to 4, to 1, to negative 2, to negative 5, and so on, to negative infinity, since i will never actually equal 0. And then at the end of this program, we have the foo function which is going on print out that i. So this is a short and trivial program, and the bug is obvious, especially after I just said what the bug was. But the intent here is, well, this might actually look like some of your solutions from greedy from the last problem set, and maybe you do have some infinite loop in your program, and you have no idea what's causing it. So a very useful debugging technique is to just add printfs all over your code. So here I want a printf outside first while loop. And here I want a printf, and I'll just print i. I'll even do first while loop, i. Outside, second while loop. Once again, print inside of here, the value i. And let's run this. So dot slash debug. Enter an integer. Let's do 13. And boom. We see that we are infinite looping inside of the second while loop. So now we know what the bug is. But printf debugging is perfectly great, but once your programs get longer and more complicated, there are more sophisticated solutions to getting things working. So let's remove all these printfs. And let's make sure I didn't break anything. OK. So the program we're going to introduce is called GDB, for GNU Debugger. Well, actually, let's remove debug for a second, and make debug again. Well, actually first, a good lesson in command line arguments. Notice that this Clang command that is compiling everything is being passed at the command line, these command line arguments. So exactly how you are going to be using command line arguments, as we did before, and as you will in PSET 2, that's how Clang is using them. So notice that this first flag, dash ggdb3, what that's saying is, Clang, you should compile this file with the intent that we will eventually need to debug it. So as long as you have that flag, then we can GDB debug. And it'll open up the GNU Debugger. So there are a lot of commands that you need to get used to. First one that you'll probably immediately need is Run. So what is Run going to do? It's going to start our program. So run, starting program, the program asks us for an integer, 13. And then it's infinite looping as expected, except I removed the printfs, so we don't even see that. Exited normally. Oh. It's possible that it wrapped all the way around, back to-- ignoring that. Assume it did not exit normally. There's a complicated answer to that. So now, that's not very useful. So just running our program inside of this debugger doesn't help us in any way, since we could have just done dot slash debug from outside GDB. So the one command that you'll probably-- and I'll quit this. Control-d or quit, both work. So let's open it up again. Another command that you'll probably immediately want to get used to is Break. So we'll break on main for now, and then I'll explain that. Well, here we see we set a breakpoint at this line in debug.c. So what break means is that when I type run, the program is going to continue running until I hit a breakpoint. So when I hit run, the program starts, and then it breaks as soon as it enters the main function. Break main is going to be something you pretty commonly do. And now, to introduce you to some more commands. Notice here, that it's saying we broke at line 11, which is printf, enter an integer. So the command Next is going to be how we go to the next line of code. This is going to allow us to step through our program line by line. So next. Now line 12, we're going to get the integer. Next. And if you just hit Enter again, it'll redo the last thing you did. So I don't need to type next each time. So enter an integer, 13. So now, line 14, while i is greater than 10, and I'll do next. And we see we're going to decrement i. So we're going to decrement i again. So now, another useful command is Print. So Print is going to print out the value of the variable. Let's bring out the value of variable i. Let's print i. It's going to say i is 11. Now we Next again while i is greater than 10. So i's still greater than 10, since it's 11. i minus minus. Let's print i again. As expected, it's 10. So now, next. It's going back to the condition, i is greater than 10, but i is now 10, so it's not greater than 10, so we expect it to fall out of the while loop. And now we're below that line of code. And another command, List, is just going to display the previous and next couple of lines of code, in case you lost yourself. So we just exited this while loop, and now we have entered this while loop, line 18. So while i does not equal 0. And, next, i equals i minus 3, and we'll notice, this'll just keep going. And we can print i. Each command sort of has shortcuts. So p is short for Print. So we can p i. Just keep holding n, or keep doing Next. Print i again. You see now it's negative 167. So this will go on forever, but not really forever, since you just saw, it will actually end at some point. So that is Beginning GDB. But let's do one more thing in GDB. Uh, debug. So, in this particular case, the infinite loop happened to be inside of the main function. And for now, just accept that that I'm going to move the infinite loop into the foo function. Just remember that, at the end of this program, well, this was originally calling foo, which was just going to print i. But now we're calling foo, which is going to decrement i until it's 0, and then print that variable. OK. Save that. Make debug. And now, gdb debug. OK. So if I just Run then I'm not going to be able to actually step through my program line-by-line. So let's break at main, and then type run. So go through this, printf, enter an integer, get the integer, 13. So we're going to keep decrementing until i is greater than 10. Then we're going to fall through the while loop, and get to the line-- let's open it up in a separate window. So we decremented until i was no longer greater than 10, and then we called the function, foo. So what happened as soon as I hit function foo, well, I called foo, and then I no longer had control over GDB. So as soon as I hit Next at this line, things continued until this happened, where the program exited when-- assume it didn't exist eventually. You saw it pause for a bit though. So why did I lose control over the program at that point? Well, when I type next, that goes to the literal next line of code that will execute. So after line 21, the next line of code that will execute is line 22, which is, exiting from main. So I don't want to just go to the next line of code. I want to go into the function, foo, and then also step through those lines of code. So for that, we have an alternative. Let's quit that again. Break main. Uh, 1, next, next, 13, next, next, next, carefully, before we hit line foo. OK. So now, we're at line 21, where we call foo. We don't want to type next, since that will just call the function foo, and go to the next line of code. What we want to use is Step. So there's a difference between Step and Next, where Step steps into the function, and Next goes over the function. It just executes the entirety of the function and keeps going. So Step is going to bring us into the function, foo. And we see here, now, we're back at this while loop that's, in theory, going to continue forever. And if you hit Step, when it isn't even a function to call, then it's identical to Next. So it's only when you're at a line that is calling a function that Step is going to differ from Next. So Step will bring us here. Step, step, step, step, step, step, and we'll just infinite loop forever. So you might get used to that as your way of identifying infinite loops, is just holding this Enter key to see where you get stuck. There are better ways to do that, but for now, that is perfectly sufficient. And stylistically, to conform to Style 50, I should have done this. OK. So one last command to introduce. Well, let's gdb debug in. So instead of breaking at main, if I know the foo function is also the problem, then I could have just said, break at foo, instead. Let's say I break at both main and foo. So you can set as many breakpoints as you want. When I type run, it's going to stop at the-- ooh, let's recompile, since I changed things. You'll see this line, Warning, source file is more recent than executable. So that means that I just went in here and changed these to conform to Style 50, but I did not recompile the program. So GDB makes me aware of that. I'll quit, make debug again, hit gdb debug. OK. So now, back to what I was doing. Break main, break foo. Now if I run the program, so it's going to continue until hits a breakpoint. That breakpoint happens to be the first one at main. Now, instead of doing next, next, next, next, next, until I hit foo, I can type continue, which will continue until you hit the next breakpoint. I have to enter the integer first. Continue will continue until I hit the next breakpoint, which is that function of foo. So Run will run until you hit a breakpoint, but you only type run when you're starting the program, and then, from then on, it's continue. If I just did break main and then ran, it'll break at main, and then continue. Since I don't have a break point at foo, enter the integer, then now I'm not going to break at foo. It's just going to infinite loop until that. OK. So that's Intro to GDB. You should start using it in your problem sets. It can be very helpful to identify bugs. If you actually just, line-by-line, go through your code, and compare what is actually happening with what you expect to happen, then it's pretty difficult to miss your bugs. OK. So last week David brought up this secret-key cryptography stuff for the first time, where we don't want passwords just be stored on our computer in some plain text file, where someone can come over and just open it up and read them. Ideally, they would be encrypted in some way. And in Problem Set 2, you'll be dealing with one method of encryption, or, well, two methods, but they aren't so great. If you do the hacker edition, you're also going to be dealing with decrypting some things. So the issue now is, well, even if we have the strongest encryption algorithm in the world, if you choose a particularly poor password, then it won't help you very much, since people will still be able to figure it out. Even if seeing the encrypted string and it looks like a mess of garbage that means nothing to them, if they still just need to try a few passwords to figure it out, then you aren't very secure. So watching a video that makes that point. [VIDEO PLAYBACK] -Helmet, you fiend. What's going on? What are you doing to my daughter? -Permit me to introduce the brilliant young plastic surgeon, Dr. Phillip Schlotkin, the greatest nose job man in the entire universe, and Beverly Hills. -Your Highness. -Nose job? I don't understand. She's already had a nose job. It was a sweet sixteen present. -No. It's not what you think. It's much, much worse. If you do not give me the combination to the air shield, Dr. Schlotkin will give your daughter back her old nose. -No. Where did you get that? -All right. I'll tell. I'll tell. No, daddy. No, you mustn't. -You're right, my dear. I'll miss your new nose. But I will not tell him the combination, no matter what. -Very well. Dr. Schlotkin, do your worst. -My pleasure. [TOOLS BEING SHARPENED] -No. Wait. Wait. I'll tell. I'll tell. -I knew it would work. All right. Give it to me. -The combination is one. -One. -One. -Two. -Two. -Two. -Three. -Three. -Three. -Four. -Four. -Four. -Five. -Five. -Five. -So the combination is one, two, three, four, five. That's the stupidest combination I ever heard in my life. That's the kind of thing an idiot would have on his luggage. -Thank you, your Highness. -What did you do? -I turned off the wall. -No you didn't. You turned off the whole movie. -I must have pressed the wrong button. -Well, put it back on. Put the movie back on. -Yes, sir. Yes, sir. -Let's go, Arnold. Come, Gretchen. Of course, you know I'll still have to bill you for this. [END VIDEO PLAYBACK] ROB BODEN: All right. So now that we're already talking about security in some ways, nice little movie poster, so in recent days, these issues with the NSA monitoring everything. It can be difficult to feel like you have some sort of privacy in the online world, although I couldn't tell you most of the details of PRISM. So moving beyond PRISM, we're not going to be talking about that, now think about your laptop. So up here, I want to switch to my actual account, with my little penguin. So I have a password set, and that password is whatever I want it to be. But remember that what I'm logging in with, so this login prompt, is some program. It's some program that was written by some person. And so, that person, if they are particularly malicious, they could have said, all right, so if the password that I enter is equal to my actual password, or it's equal to some special password-- David is awesome or something-- then let them in. So a malicious programmer could have access to all of your Macs, or Windows, or anything. So that isn't much of a concern, since, I mean, this is login program that's shipped with OS X, hundreds or thousands of people have reviewed this code. And so, if, in your code somewhere, you say if this string equals equals David is awesome, login, then someone's going to be, like, wait. This is not right. This shouldn't be here. So that's one way we get things to be kind of secure. But think about even programs that you write. Let's say you wrote the login program. So this login program that you wrote, so obviously, you are a good programmer. You're not going to put any malicious if x equals equals David is awesome into your code. But this program, what do you use to compile this program? Something like Clang. So what if the person who happened to write Clang special cased in Clang something like, if I am compiling the login program, then enter this code into the login program that says, if x equals equals David is awesome? So not quite yet, but we have the same issue here, where Clang, well, thousands, if not tens of thousands of people, have looked at Clang, have looked at its lines of code and said, all right, there's nothing bad here. Obviously, no one is doing anything this malicious. But what is Clang itself, like, what if I compile Clang? What if I have some compiler that compiles Clang that inserts into Clang this special hack that says, all right, when I compile Clang, then the executable I get should specially look inside of the login program and insert this password, equals equals Dave is awesome? So remember that your compiler itself needs to be compiled at some point. So if what you choose to compile Clang with, itself is malicious, then you could be screwed the whole way down the line. So here, we have Ken Thompson and Dennis Ritchie. So this is an iconic photo. Dennis Ritchie is on the right. He is a major-- pretty much wrote C. So you can thank him for this class. Ken Thomson's on the left. The two of them basically wrote UNIX. Well, they were major contributors in UNIX. There were some others. So Ken Thompson, at some point, he wins the Turing Award. And the Turing award, I've always heard it referenced this way, it's the Nobel Prize of computer science. So at the Turing Award, he has to give his acceptance speech. And he gives this very famous speech now, called Reflections on Trusting Trust, which we have linked to on the course website. And in this speech, he says, all right, so I wrote UNIX, and now all of you people are using UNIX. Now, remember today that Linux is a direct descendant of UNIX. OS X directly uses UNIX. Windows doesn't so much, but a lot of ideas were taken from UNIX. So he goes up to the stage and says, all right, I wrote UNIX. And just so you guys know, I'm able to log into every single one of your computers. Since I put one of these special if x equals equals Ken Thomson is awesome, then I'm allowed to login. So people are like, well, how'd you do that? We looked at the login program and nothing's there. He's like, well, I modified the compiler to log in the login program so that the login program now will have that x equals equals Ken Thompson is awesome. And they say, well, that's not true. We're looking at the compiler, and the compiler doesn't have any lines of code like that. He's like, OK, but what are you compiling the compiler with? And they think, and he's, like, well, I'm the one who gave you the compiler you're using to compile the compiler, so you are compiling a compiler, that itself is malicious, and will break the login program. So basically, at that point, there's no way you could look at the source code of the login program to see what is wrong. You couldn't even look in the source code of the compiler to see what is wrong. You would need to look at the machine code, the actual binary of the compiled compiler to see, wait, these lines of code should not be here. But Ken Thompson took it one step further and said, well, there are these special programs that actually help you read the binary of programs, and so if someone used that program to read the binary, they would see these lines of code. He modified those programs to say, all right, if you're looking at the compiler, don't show this particular set of binary. So then you need to take that a step further and basically, that could have taken multiple levels of indirection, and at some point, no one's actually going to be checking. So the moral of the story is, you're not going to be writing Clang in this class. You're going to be using climbing Clang a lot in this class. For all you know, Clang is a malicious program that is sabotaging every single program you've ever compiled. And to leave you on that very ominous note, see you on Wednesday. [APPLAUSE] SPEAKER 2: At the next CS50. SPEAKER 3: Don't you dare say that. You can do this. You've done this before, you can do this today, you can do this tomorrow. You've been doing this for years. Just go up there and do this. You can do this. [MUSIC PLAYING]