[ Silence ]
>> This is CS50, the end of Week 2.
So I thought I'd begin with a short note that one
of your classmates sent to me earlier this week.
I'll leave it anonymous but read the content.
Your lecture -- I don't normally do this with your emails --
but your lecture the other day reminded me of this scene
from The Computer Wore Tennis Shoes.
If you've never seen it,
I'd highly recommend it just for the technology.
Obviously, it is a little old, but it is funny
to see what people thought about computers in 1969.
So I give you a scene from The Computer Wore Tennis Shoes.
>> [Recorded Demonstration] Computer our input,
memory control, arithmetic, and logic and output.
I think we can see demonstrative from these charts,
that man has done a rather admirable job
of imitating the human brain.
And even though it's an imitation, in many ways,
the machine that we've developed can operate more
than we can ourselves.
And now in the past couple of weeks, I've been working
on a small experiment, which is intended
to show how we can be replaced by a computer.
>> Hey, this may be a way of getting rid of Dean Higgins.
>> We live in hope Dexter.
And now let's suppose that your parents are going away
for the weekend and they leave you
with the following instructions:
If it's raining tomorrow morning, when you wake up,
you are to close the windows, open the door
and let the cat in, phone the grocer and have him send
over the following list of groceries.
All right.
Well, you wake up in the morning and it is raining
and being the conscientious and reliable young people
that I know you to be, you probably forget to do it.
Well, actually, I'm sure you would do it.
But let's see if a computer could also do it.
Now this is a rain gauge, and it's sitting on a roof
of a building, and when the water falls into this gauge,
it sends a signal to the logic unit of the computer,
which immediately notifies the memory bank of the computer
to seek out its instructions for a rainy day.
The memory bank, in turn,
activates the electronic circuits; the window closes,
the door opens, hopefully the cat comes in,
and the automatic telephone goes into action; right?
Well, let's see.
[ Electronic Noises ]
>> The rain falls.
[ Electronic Noises ]
>> This is a recording.
Please deliver the following groceries to 445 Attic Street:
1 pound of bacon, 2 dozen eggs, 4 quarts of milk.
>> Well, that's enough of that.
[ Applause ]
>> Thank you.
Thank you.
Well, so much for the speed of the computer.
Now another very important feature is its
infallible memory.
Before, this computer was owned by the AJ Arnold Company.
It used to be employed by the Space Research Center
at the specific Institute of Technology.
And they were kind enough to send us this magnetic tank
which we'll call forth from the computer solutions to a series
of problems that would occur
on a simulated flight to the planet Saturn.
Now, mind you, it was 20 years ago
that this program was operational, 20 years.
Well, if you'll watch the center panel, please.
[ Electronic Noises ]
>> Well, it seems like our flight
to Saturn will be a little delayed.
>> In any case, that high school has like $10 million worth
of computer equipment apparently in the front of it.
Computers don't have so much the same kind of blinking lights.
There's an allusion there to memory,
which will be a little apropos for Problem Set 2.
For Problem Set 1, as you may have seen already,
what I thought I'd -- I had not, in fact, seen that clip;
so I did a quick Googling and that's actually as relevant
as the movie really gets I think to computing.
If you read a quick plot summary here,
I'll just give you a little teaser.
All right.
This is more of a spoiler alert,
but you've had 41 years to see this movie.
So Kurt Russell and his friends attend a small private college,
which cannot afford to buy a computer.
The students persuade wealthy businessman
to donate an old computer to the college.
He is the secret head of a large illegal gambling ring
which use the computer for its operations.
While installing a replacement part during a thunderstorm,
Riley, the Professor, I presume, is zapped
and becomes a human computer.
He now has super-human mathematical talent, can read
and remember the contents of an encyclopedia volume
in a few minutes, and speak a language fluently
after reading one textbook.
Riley, single-handedly, leads Medfield's team in victories
against other colleges.
During the tournament, a trigger word,
that causes Riley unknowingly to recite on television the details
of Arno's gambling ring.
Arno's henchman just goes on.
So an interesting movie but a fun clip, perhaps, nonetheless.
So a few announcements and those are: one, sectioning.
We've had super sections, as we called them this past week,
really to -- available to anyone who would like to attend.
This coming week, we'll start a more traditional
assigned sections.
The sectioning tool,
FAAS Sectioning Tool will be available to you later today.
We're just waiting for confirmation on some time.
We'll post an announcement to the course's homepage
at CS50.net on the top with a link.
So if you want to check that out after dinner time or so,
you can fill that out.
And we will close sectioning by this Friday at the time
to be stated on the course's website.
Inevitably, in a class of this size, we're going to have
to make some adjustments; so you'll receive instructions
when you get your section assignment on how to deal
with unforeseen conflicts if, for instance,
some other class just moved you around.
If you have been working and are still working
on problem Set One, do realize that a good deal of support
and assistance is available to you.
So this is our little Google calendar that we embed
in the course's website, and this is the number
of office hours we had just in the next couple of days alone.
If you look at this in graphical format, I mean,
it's actually pretty remarkable just how many
of us will be down there.
So it's in Science Center B14, which is,
you go into the Science Center, you go down the steps,
turn left, and there's a pretty big computer lab there.
The way the workflow generally works is you just grab a
computer or bring your laptop.
We use the whiteboards alongside one of the walls,
where you just write down your name if you have a question.
We just go through the list top to bottom, left to right,
and cross names off as we go.
Realize that there's an inevitably challenge for us
and actually helping people in this kind of context,
especially as the deadline really approaches.
So do view these particular office hours.
It's definitely an opportunity for help, but particularly,
as an opportunity to work with someone for just a few moments
to help get you unstuck
or to get you past some stumbling block that, otherwise,
if you struggled with on your own, you might sink
or waste even multiple hours on just something
that you're not seeing.
So if you have more conceptual oriented questions,
you can absolutely bring them to office hours,
but just realize there's always a crunch time wise,
especially on Wednesday's and Thursday's.
So do reach out ultimately to your assigned teaching fellow,
to me, to the help list, to the forums online.
If you'd like to sit down with one of us more intimately
and more sort of tranquilly, and work through problems for more
than just a couple minutes at a time.
So with that said, this --
these forums, I'm referring to are these at help.cs50.net.
Our bulletin boards of sorts, discussion forums,
where you can not only browse discussions,
questions that your classmates have asked,
you can certainly ask questions of your own.
If you would like to flag them as private,
because you just don't want your classmates
to see what you're asking, you can certainly do that.
And if you're sharing a particularly decent amount
of code, you should definitely submit it as private,
or if easier, you can email help at cs50.net.
And realize too, as we say on this home page here, by default,
we anonomize you when you log into this bulletin board,
whereby, you're all logged in as quote unquote students.
The staff can still figure out who you are in order
to help you most effectively but as for your classmates,
they'll just see you and your questions as student.
And this is very much deliberate on our part
so you just don't feel that inevitable angst when it comes
to asking what you think is a dumb question
and probably isn't, but you don't need
to disclose your name.
And if you do wish to disclose your name, you certainly can,
per the directions on this page.
So with that said, let me go ahead
and mention one other thing.
So one of the other features available is a link up top
on the course's office hours page that will lead you
to what we call the Vrtual Terminal Room.
The Virtual Terminal Room is really a glorified chat room,
but it's a piece of software that you can log into,
via the office hours page, as yourself.
After logging into the course's website, you'll appear
on the top left-hand corner as I just did with your actual names
that we know exactly who we're working with
and then what you can do is raise your hand sort to speak.
There's a little icon of a hand here, at top left, you go ahead
and click that, and what happens is, we, the staff,
see a little blinking icon in the top left that says one
out of two hands, one out of 10 hands, or some number of hands,
and it maintains in the little row
up there your placement in line.
So this is pretty much a computer version
of the whiteboard in the Science Center.
The goal of virtual office hours is if you're sitting
down in mather or the quad or wherever, even off campus
on some weekend, we'll still hold, not as many,
but some virtual office hours.
So you can log into this, not only chat
with this interactively, but on the right-hand side here,
which is just a wallpaper right now,
you can actually grant us view or control of your own screen.
So if you've got putty or terminal up on the screen,
and you're having some trouble that's really best seen with --
in that natural environment, we can actually see sort
of tech-support style
on the right-hand side what you're doing,
and you can see everything we're doing.
You have to grant us control explicitly.
So do keep this in mind as an available option as well.
Lastly, that was it.
Let me go ahead and -- oh, that's nice, someone learned how
to send right messages on the cloud.
All right.
I'll write you back later.
So that brings us back to --
it's a feature that will be disabled by tonight, I'm sure.
Well done, though, class.
All right.
Oh, so a couple of -- oh, okay.
So a couple of FAQ's that have come up in section
or rather in office hours.
So we keep track of the types of questions that come up,
unless I said something stupid in class
or been confusing, certainly.
So what I wanted to do is loop back, at least with a couple
of things that we see recurring and very understandably so,
but let's try to clear up a couple
of frequently occurring issues.
So we've seen a lot of this, for instance, in office hours
and maybe you too have done or are currently doing this,
but there's a problem with writing a statement,
like print F, followed by, get int, alone.
So someone who's a little more comfortable with this
at this point, what's the problem here?
Or what is the problem?
>> You don't know where to store it as one.
>> Yes. You don't actually store the return value of, get int.
So we'll talk a bit more about this idea of functions today,
but, get int, again, can think of it as a black box,
whose purpose in life is to prompt the human for input
and pester the human if he
or she doesn't actually give it int, but then once it has that,
has entered it from the user,
it's quote unquote, returns it to you.
But if you don't actually do anything with it,
it simply disappears, and, therefore, it's --
well done, classmate Number Two.
The beeping means a hello message.
Let's see.
Just to illustrate this point, I thought it would be more fun
to do this without just me.
But two of you, if you would
like to come up for just a moment.
Volunteers.
>> I'll do it.
>> Yep, come on down.
And how about in the purple there.
Yep, purple, pink, come on down.
Oh, and darker purple, okay, darker purple.
Okay. Three volunteers.
I will make up a third row somehow spontaneously here.
All right.
So why don't you have a seat on the chair
on the right-hand side there.
All right.
And why don't you have a seat in the second chair.
And why don't you come here and wing this with me.
So what are your names?
>> Christiana [Assumed Spelling].
>> Christiana.
And?
>> Jordan.
And?
>> Karen.
>> And Karen.
Okay. So just to illustrate this point,
and then we'll actually use this in a co-oriented environment.
Suppose that Christiana is a function.
Let's call her, get int, for today.
Jordan's going to play the role of human.
And so I have equipped my function with a whole bunch
of memory, which we'll implement in the form of old-school paper.
We will equip Jordan, meanwhile,
with a keyboard or an old-school pen.
And now Christiana if you would -- your goal --
your role here -- no, let's see.
I'm still trying to work out a role for you
so hang on for one sec.
So your role in here in this demo is
to get an int from Jordan.
So go ahead and prompt Jordan for an int.
Say something like, give me an int.
>> Give me an int [Laughter].
>> All right.
So Jordan, playing the role of human is going to type
or write something down on this piece of paper,
hand it back to, get int.
So inside of get int's memory, shall we say, is this, in fact,
int, which is the number 10.
It looks at the [Inaudible] but we don't know that yet.
And here I finally have a role for you.
So now if Christiana doesn't actually --
if either programmer or who's programming these little puzzle
pieces, don't actually do anything with this return value,
and I call, get int, she wants to hand this piece of paper
to me, but if I don't actually assign --
no, no, I just messed up the demo.
So if you don't actually assign to something,
it falls on the floor and the value goes away.
It was a complete waste of time, unless the goal
in life was simply to pester the user for some input.
So now if we actually introduce the variable X,
welcome X. Let's do this again.
Let's try a different number just
to make the demo more interesting.
Get int, if you will.
>> Give me an int.
[ Demonstrating ]
>> All right.
This time we have the number 100.
And so this time when you hand it back, this value,
I store it in -- we'll say X,
and now we actually have retained the value.
So I realize that this was among a more childish demonstrations
that I could come up with to illustrate this point.
But odds are you'll never again do that on the screen.
So a big round of applause for our volunteers, if we could.
[Applause] You can keep that for a souvenir, if you'd like.
And if you could just meet up with the teaching fellows
for our little -- our legal department, that would be great.
All right.
So there's one other detail.
>> Right here.
>> Yeah. Right this way.
>> Oh, okay.
>> Thank you Number Three.
All right.
If someone could figure out how to turn off messages,
that would be great [laughter].
So this will be an interesting class.
So the second common thing that we saw was a syntax like this.
Right. So right ideas.
You're definitely borrowing some
of the pieces that we've looked at.
The curly braces to encapsulate one or more lines of code.
The semicolons to terminate lines.
The parentheses to pass in inputs
or arguments to functions.
But if you throw them altogether,
things tend not to work.
All right.
So this is a thing, Week Number Four, saw very commonly,
which was -- this is something we saw commonly
and there's a couple of issues here.
And this isn't, you know, to point out the flaws
in someone specific, but to point out some
of the common mistakes.
So what's one mistake that's apparent to some here?
Point out what makes you be the obvious.
What is here that shouldn't be here?
[ Inaudible ]
>> All right.
So we don't need the curly braces.
The curly braces, really, we've only deployed in contexts
like loops, wild loops, do wild loops, four loops, where we want
to encapsulate one or more lines of code,
all inside of some conceptual idea
like a condition, like a loop.
Here, print F, recalls a statement and just
like in scratch, statements were these one-liners.
I think they're purple or so in scratch, or yeah, purple,
I think, generally; say hi, for two seconds.
Right. So similarly, if you've got one line of code
with a semicolon at the end saying, this is the end
of the statement, it doesn't really make sense to continue
that conversation to try to continue conceptually
that puzzle piece with curly braces.
Now as an aside, this may very well compile.
In fact, this example would compile
because you can use curly braces in this way to encapsulate lines
of code, but realize for now, that, not good.
Only use these for conditions, only use these for loops,
and it is, in fact, correct to put the semicolon
in on the end here but not, for instance, in a case like this;
if I, by contrast, do it for int, I get zero;
I is less than 10, I plus, plus; and then I do this,
because I'm in the habit of ending my lines with semicolons,
and now I go inside my loop like I was --
like I learned to do and I do something,
there's a problem with this.
All right.
So it's definitely the semicolon.
But what does the -- what is the effect
of that semicolon would you conjecture?
Yeah. Let's go here.
>> It just ends.
It stops looking for more things to use.
It tries to evaluate the loop as [Inaudible].
>> Okay. So that's true.
It ultimately evaluates that line of code
but just once the stuff inside the curly braces,
but the semicolon on the end,
essentially has the effect of this.
Go ahead and define your loop.
Do nothing, close your loop and then down here do something.
So in other words, if you terminate these lines early,
if you terminate the four loop early, if you terminate an
if condition early with that semicolon,
the code may very well work; and this is a common source
of frustration and conundrum because you don't --
because your code looks right and yet it's misbehaving,
but that semicolon means stop looking
for subsequent lines of related code.
So if you do include it up top, the subsequent lines,
even if you have these curly braces, are not,
in fact, going to help you.
So the take-away for now, I would say, --
is this all software work, yes, good.
The take-away for now is really to look back at some
of the examples we've seen in lecture, some of the examples
that you've now seen in the super sections
and in the future sections really, for guidance.
It's deliberate that a lot of the examples
in lecture are fairly short and bite-size
so that you can actually focus on pulling out the key ideas
without getting distracted by line and lines of code.
And I'll point out as we proceed, because I kind of have
to start using the cloud here.
It's your user name that appears in these messages.
So we'll say hello to you later, if need be.
So with that said, scary voice Number Two.
All right.
So functions and return values.
So just to hammer home this point, for now,
a function really is like a black box.
It's something that someone else wrote or maybe you wrote,
but you can encapsulate all of your ideas
or your functionality inside this thing called a function.
And its purpose in life is to maybe take input
and maybe produce output.
But if it does take input, you have to provide it in the form
of arguments or parameters, like print F takes, generally,
inside of those parentheses.
And if it returns a value, you've got to do something
with that return value too, much like we did up here.
You got to store it in a variable.
You have to pass it as input to another function, as you'll see
as possible in problem's Set One specification,
but it's ultimately up to you.
So let's take a look
if you still have your printouts from Monday.
We have a couple of examples in -- among those printouts,
this one called, return one dot C. So in here,
you'll notice a couple of key things: so one,
a wave of the hand, for the moment, at this int arg C,
and this char Arg V. We'll come back to that today
when we introduce more formally the idea of arrays
and command line arguments,
but there's a couple of other curiosities.
For some reason, at the top of this file,
I've also included what I've called a function prototype.
So we'll see in a moment why that's necessary.
And, in fact, it kind of looks like a function,
and yet here's a semicolon I just said that can get you
into trouble, and yet that's not actually a function,
because there's no interesting lines of code, because it turns
out the interesting code is down here at the bottom.
So it turns out that, main, yes,
is the default function you write, at least in C,
when writing a program.
And the computer just knows that when you run a program,
it should look, by default, for a function called main,
as opposed to one called print F or anything else
for a function called main and execute that one and then it's
up to you to call other functions
like print F, if you want to.
Well, you don't have to just take what you've been handed
in life, functions like print F or round
or maybe other functions you've seen
in super sections or by poking around.
You can certainly implement your own.
Now this is not a particularly compelling pace just
yet of implementing your own function.
But let's suppose that I realize that I'm doing a lot of addition
in my programs, and I actually want to factor out what seems
to becoming a lot of copy, paste.
I keep seeing addition
and I keep just copying my code, copying my code.
Anytime you find yourself in this pattern, odds are,
what you're doing is a candidate for being factored out,
hierarchal decompositions is the buzzword you'd see
in the textbooks if you're following along with any
of them, but it's really just the idea of taking
out common code and putting it into just one place.
So how do you define a function?
We have to decide three things: one, the name of the function.
And just as with variables, you should use some common sense,
some style here, and the function's name should
communicate what it does, calling it X or Y
or Z is generally not all that helpful.
It then should take an argument or parameter
if you want your function to take input.
If you want it to take a so-called argument
or a parameter, there's a subtle semantic distinction
between arguments and parameter, but for all intents
and purposes, they're the same thing.
An argument or a parameter is an input to a function.
Now in this case, it's clear
that I'm not only saying this function takes an input,
I also have to give that input a name.
Because if I don't specify a name for this input,
I have no way of actually referring to it
in subsequent lines of code.
Now I seem to be violating my own mantra here
by just calling this variable A, but this is reasonable,
much as with four loops when you just call an incrementing
variable I, because you just need an index, well, same here.
If you're writing a one line function, whose sole purpose
in life is addition, and, clearly, this is about addition,
well, then it's, in fact,
reasonable to use a shorter symbol like A,
but I do have to specify it's type.
So here's where C differs from some language
that you might be familiar with and from languages
that you'll see later in the course, like PHP and JavaScript.
You have to be ever so explicit
as to what data type your actually passing in.
So that's one, the name.
Two, the arguments or parameters,
and three, is the return value.
So you're implementing this black box, and if its purpose
in life is to actually return a value,
you have to tell the compiler what kind of value to expect,
and this is going to have ripple effects.
If this function increment is defined as or declared as,
as we say, returning an int, you have to make sure
that if you're doing something with the return value,
that you're storing it in the same type of the variable,
like an int variable or you're passing it to print F
with percent D that you're using it in the appropriate context,
unless, as an aside, you intend to typecast it,
which we've discussed, if briefly.
All right.
So what's for all this function --
what's the role of this function in life?
It returns its argument plus one, that's it.
Now it's a stupid little function.
We could certainly implement this much more efficiently
by just writing this one line of code, but, again,
the key here is to take this step toward decomposing our code
into chunks of code.
So much like you did was scratch,
some of you might have implemented these very
unwielding programs, and that's fine because you're kind
of constrained in scratch.
You don't have these kinds
of design capabilities to the same extent.
But a lot of you did realize you can have multiple one green flag
clicked scripts and so you can factor things
out to have different sorts of roles; so same idea here,
even though in scratch you can not call functions
that you yourself wrote.
There's no notion of naming a script
as you can a function in scratch.
So here's the main function.
What does this thing do?
Int main. Lets ignore what's inside the parentheses for now.
Int X gets two; so that declares four bytes of memory
and stores inside of them the Number 2.
This is just aesthetics.
X is now placeholder.
What do I place?
The value of X. Now I say, incrementing dot, dot, dot,
just to convey the idea of some progress,
and now here is a so-called function call.
We've seen function calls before.
You've used get int, get string, or the like perhaps already.
Well, here, I'm calling my own function, increment.
It's defined later down which is fine.
I'm passing an X, and yet I'm also assigning the return value
to X. So just intuitively what's going to be the effect
of this one line of code?
[ Inaudible ]
>> Right. So to do X plus, plus.
So, again, this is why I'm disclaiming that this isn't all
that interesting yet, but what am I doing.
I'm passing as input the value in X, which is two.
I am then doing some mathematics with it,
clearly, based on the below.
I'm returning the result of that summation;
so it's probably now three, but when I get that three back,
if I don't actually do anything with it, like assign it,
it's all for not, and so I decide arbitrarily here
to assign it back to X, and so the end result,
in this particular case, is indeed,
identical to saying X plus, plus,
but now we have the framework in mind or the capabilities
and code to start doing more interesting things
with functions like this.
And actually, if I don't want to clobber, as we say,
overwrite the value of my variable,
I could declare another one and store the return value in Y;
so now I have two ints in memory; X and Y,
one with two, one with three.
But in the end, because I'm taking this approach,
if I proceed with the remaining two lines,
it says incremented X is now hopefully three
and that should be a working program.
So let's take a look.
Let me go ahead and compile return one.
All right.
Everything seems to work.
So let's go ahead and run return one, enter.
So it does, in fact, seem to work.
But there's a key line of code that I lost over a moment ago
and that was this one here.
I have my includes, standard IO's; so I can use print F,
but then I had this thing called a prototype.
Let me actually get rid of that for just a moment.
Re-save my file, and actually now recompile with make.
So now I've got an issue all of a sudden.
I just reran make or GCC does it for me,
and now I've got all these errors.
Well, let's see.
In function, main.
All right.
That's not helpful yet.
Okay. Interesting.
So here's a tip if you've not picked up on this already.
If you're getting these compilation errors, well,
when you compile, notice there's a number of key help --
the number of helpful tidbits here.
So one, is obviously the filename
that I've been working on.
Colon 21, though, for those who are already familiar,
is a line number; right?
And nano, though it's a primitive program,
we deliberately turned on a feature where if you scroll up
and down, it literally tells you at bottom left,
what line you're on; so that can help you narrow
in on the problem you're having.
What was that problem?
Let me move it higher up.
What was that problem?
Implicit declaration of function increment.
So here's where C is kind of showing its age.
It's kind of a stupid lack of feature that this is the case,
but notice that here is main, at the top of my file.
I like it at the top of my file.
It's the first thing that gets executed.
It makes sense to me logically that I want to see it first
when I open the file; so I scroll on down
but only later is increment declared.
So C or the compiler's for C are kind of dumb, by definition
of the language years ago, whereby, they only know
about what they've already seen.
So even though increment is obviously declared and defined
in this function, it's later; so it's too late
for me to use it in main.
So I have two solutions here; one, what would be sort
of the obvious sort of hackish or solve it fast solution?
[ Inaudible ]
>> Right. Just move it to the top; right?
Delete those lines of code and move them
up to the top and problem solved.
Now downside of this, well, I've just now violated my preference
for having main up top, maybe that's forgivable.
But very soon will you find that if you're writing programs
with lots and lots of functions, and some might call these,
and these might call these, you can come up very soon
with scenarios where you can not order them top to bottom,
because everything is comingled, and there's a lot
of cross talk among all of your functions.
So, thankfully, C does provide a solution for this, whereby,
I can provide a hint, essentially, to the compiler.
It's a little redundant, admittedly,
but I include not the same function,
but just its prototype, as I say in the comment here.
What's the prototype of a function?
The prototype is just its return value, its name,
and its arguments, if any.
But a semicolon thereafter is sufficient.
You don't have to re-implement the function.
You certainly shouldn't change anything about the function.
So now, henceforth, when you say, to declare a function,
I am declaring a function here
but down here am I quote unquote defining it or implementing it.
That's the semantic distinction.
Yeah.
>> How can you name the function [Inaudible]?
>> How can I name it int A but it works for?
>> X, like there's X up here [Inaudible].
>> Really good question.
We'll explore more of this today, actually.
But this choice of names, both for my functions and also
for my parameters
or my variables is completely up to me.
What's going on underneath the hood is we'll see pictorially
today is that when I declare this X, this variable X here.
Right. I defined this last week.
It's just a little block of memory in RAM, you know,
that represents four bytes, 32-bits
and the Number Two is currently in it.
The fact that I've called it X, is really just a programming --
it's a feature of the programming language that I,
the human, can now refer to it.
Not by some very arcane numeric address inside my computer's
memory, but by a symbol, by a name.
It's just more useful to refer to it by name.
Well, I don't have to use that name for every copy of X,
and as we'll see in a moment.
When you call a function, what actually happens is
that function gets its own chunk of memory that's identical
in size to the data type that it expects.
And in this case, an int, which means, this function,
increment also gets from the computer its own four bytes.
It's own 32-bits.
And when you call a function, one of the things
that happens is whatever your passing in, for instance, X,
and if this is A, this thing gets copied into A;
so at that moment in time of calling increment,
I actually have two copies of the same value in memory
but they're referred to by different names.
But this is a -- this raises a problem, that we'll see actually
in just a moment having this duplication.
[ Inaudible ]
>> Good question.
So short answer, yes.
You can use this for nefarious purposes.
Not so much with int, because ints are bounded in size.
They are 32-bits or they are four bytes.
But once we get the strings today,
in arrays then absolutely.
This is how a lot, a lot, a lot of software
and servers are still compromised today.
So putting back that prototype allows me to compile this,
because I'm saying proactively to the compiler hey,
you're going to see a function called increment.
It returns an int.
It takes an int; deal with it when you get to it
and then once you look through the whole file,
should you find -- ultimately find the actual code
that defines or impliments this thing.
Well, let's look at a slightly different version of this.
So in return to, we have a slight variance here,
where I'm defining apparently --
declaring a function called cube.
So let's take a look down here at what I'm doing
and notice here that this is perhaps more compelling; right?
Doing incrementation, pretty useless; right?
Because I can just use plus, plus.
I could have saved myself five minutes of verbal discussion.
But with something like cube, now it's starting
to make a little more sense; right?
Not to harp on the mathematical features of this, but cubing,
you know, if you're starting to do AX star, X star, X,
every time you want to cube some value in a program,
it just feels like this is going
to get a little messy looking, if nothing else.
And conceptually, the idea of cubing a value feels
like you could package that up into a little box, a little tool
that takes input, a value, and returns output the answer
so you don't have to constantly do A star,
A star, A, and so forth.
So this program ,at the end of today,
is pretty much the same thing.
I'm taking an input.
I'm returning some value.
But now at least we're a step closer
to doing something that's a little bit more compelling,
but this isn't always a good thing.
So it turns out there's this issue of scope here.
So when you define a function, you have,
as we've seen these curly braces, that define all
of the code that's associated with that function;
open curly brace code,
close curly brace, that is the function.
These functions thus far have been short.
They've just added a number or they've multiplied a number
of couple of times, but they've each had what's called their own
scope, and, by this, I mean the following: If we go ahead
and open up buggy three, the clue already is that there is,
in fact, going to be a problem with this, because my purpose
in life here is a little more interesting,
for whatever reason.
I've decided that I need to be able, in my program,
to swap the value of two variables.
All right.
Now I could do this pretty easily in just
by reasoning through it; right?
If I have two values -- let me go on up here --
if I've got two values, let's call it int X gets one,
int Y gets two, semicolon at the end.
So now I want to actually swap these values.
You might think -- and this board is -- and you know what,
let's use the computer because it will erase more cleanly
than chalk.
So we just upgraded.
All right.
So now we have int X gets one, -- oh, this is much faster --
int Y gets two, and now my goal in life is to swap these things.
So now at first glance, you may be a little lazy
and be all right, X gets Y, Y gets X; buck.
All right.
What's the problem here?
[ Inaudible ]
>> The murmuring is correct.
Right. So X get assigned the value of Y,
but then Y gets the value of X; so what have you really done?
Both of them now equal what value?
So both of them now equal?
>> Two.
>> I'll keep asking until we get the right --
until we all merge on the same one.
So what does the value have?
So X is getting assigned two.
So now X equals two then Y gets assigned the value of X,
which is two; so I think they are, in fact, two; right?
So you're clobbering the value of X
and then you can't get back X's value because it's too late.
All right.
So what's a quick fix?
Well, we know how to declare variables here.
So why don't we just have a temporary one.
It's reasonable because it's meant
for temporary purposes just to call it temp or T-M-P for short,
and I can define temp as -- why don't I set it as equal to X,
initially, because now that I've stored X in a separate chunk
of memory, I can now change its value and then I can say Y gets,
not X, but temp, and so now I've actually swapped these values.
All right.
So you can't do this, because you're going to lose track
of the numbers if you do that.
You actually need to kind of do this
and then you can swap these two numbers
but it requires 50 percent more memory.
It requires this additional int.
All right.
So suppose I want to do this a lot in a function.
It's reasonable to assume that I want
to implement a function called swap, that takes two arguments,
A and B, and its purpose in life is to swap those two values.
We'll, let's see what it does.
All right.
Well, it looks like I just stole my own implementation
but I happen to call it A and B, instead of X and Y,
and so here, what's going on?
Well, one, function has called swap, takes one int called A,
followed by another int called B, and as we've seen
with print F, if you have multiple arguments,
you separate them by commas.
Same deal here.
Now void, we've seen void before.
Void just means this function doesn't return anything.
Its purpose in life is to do something,
to have what we call a side effect,
but it doesn't actually return a value
because functions don't have to have values.
They only need to have values if you care
about getting something back from them, get int,
you care about its value; but swap,
I don't want to hear it again.
Just swap these two values for me
and let me move on is the reasoning.
So here, I say void.
It doesn't return anything.
So it would be incorrect to try to assign this to a variable X
or Y or Z, because it doesn't actually give me anything back.
So this code is, in fact, correct.
This code does swap the two values, A and B. However,
when I run this program, something happens.
I first print what X is.
I then print what Y is.
I then claim I'm swapping.
I then perform the swap.
I then insist, okay, swap, and then I print
out their values again.
So in theory I should see one, two; two, one.
Well, let's actually see what I see.
So let's go ahead and make this.
This is buggy three.
There are no syntax errors so it does compile.
But if I run this thing, buggy three,
they've clearly not been swapped.
So let's do a little sanity check.
Right. When in doubt, let me just use print F for now.
We'll use more sophisticated tools before long,
but let's do a little sanity check.
Let me go ahead and call print F. I'm going to say A equals
and then I need a percent D, backslash, comma A;
so this is a little bit of -- more syntax than would be nice,
but I'm just saying, literally, A equals percent D,
and I'm plugging in the value of A for percent D.
So I have little cheat sheet.
Let me go ahead and do the same thing with B.
So I have a little sanity check now.
Inside of swap itself, I'm printing
out the values, if temporarily.
Let me go ahead and recompile.
It works. Let me go ahead and rerun.
So it does seem to be working; right?
X is 1, Y is 2.
Okay. It worked.
Right. A is 2; B is 1, and yet somehow the process gets undone.
So it's almost as if functions really are useless
because they have no ultimate effect.
[ Inaudible ]
>> Okay. So it's a good thought.
Maybe the problem is that we're -- you -- well, let's see.
We're defining the function at the bottom.
[ Inaudible ]
>> Okay. So there's a couple of fixes.
Let me come back to that one.
So there's a couple of fixes here.
But why is this problem happening?
Well, just a moment ago, we did have --
and this time I'll use some chalk here --
a moment ago, we did have a picture depicting what was going
on when you call the function.
And so in main, if we called this the chunk of memory
that main owns, main has, at this point
in the story, two variables.
We called them X and Y, recall, and Y2.
Well, I said int X and int Y;
so that gave me one square here called X, one square here
or wherever, called Y, done, one was put in here;
two was put in here, and then I called this function swap.
So swap, as promised earlier, is a function.
It's given its own memory as much as it asks for.
It asks for how much?
Well, it's actually asking for three things.
They're declared a little differently.
But essentially, this A and this B,
even though we call them semantically parameters
or arguments, really they're just local variables.
So variables you were introduced to in scratch,
and there was this idea of global and local variables,
but scratch called them something a little different.
When you created a variable in scratch,
you could either make it
for this sprite only or for all sprites.
All right.
For this sprite only, means local, only this function,
only this script can use this variable, make this variable
for all sprites, meant it was global.
But thus far, we've only been looking at local variables,
which A and B essentially are, because they're defined inside
of this function swap and temp certainly is a local variable.
So swap has three chunks of memory.
It has A, it has B, and then it also has temp.
And what happens the moment I call swap, as I said earlier,
you get a copy of the inputs.
Now they have different names.
Not a problem because they're a different type.
If they're the same types, that's what matters.
So A gets 1, B gets 2, now the swap function itself starts
executing line by line; so I declare a chunk
of memory called temp.
I then store in it A. This makes a copy.
So the assignment operator thus far makes copies of things.
It doesn't move the value.
It just copies the bits.
and if the bits represent one here,
those exact same bits are going to represent one here.
So now the second line of code is A gets B, semicolon.
So what does that mean?
Well, A has to get whatever is in B. So now I'm clobbering,
as they say, this value here, and at this point
in the story, this is not good.
Right. Now I have two copies of two,
but that's why I kept this thing around.
B gets temp is the third line.
So temp is here and B is here, that means 1 gets put here
and now I print out the values.
They are correct, as the picture suggests,
but then I hit that curly brace.
When I hit that curly brace, swap's role in life is over.
There's no return statement.
He's not actually returning any value.
He's not returning A or B or temp, and definitely not X or Y;
so he just did all of this work and yet that's it.
What happens?
The moment swap returns, it says go, this never happens.
The computer essentially forgets about the memory
that was being used here, here, here for those three values.
You might very well have done some very accurate math
but it doesn't matter, because you did the math
in the wrong place.
So this issue of scope is to say that functions have scope.
And when you declare a variable, whether as an argument
or as literally a local variable,
they only live inside of that function.
The same deal in main.
It is not correct, for instance, for me to do this.
You know ,why am I wasting time passing things around.
Why don't I just do this and be clever.
Why don't I say int temp gets X. Let's say Y --
oh, sorry, X gets Y and then Y gets temp, this 2 would fail.
It looks cleaner; right?
I'm not wasting time typing out arguments
and implementing more complicated function.
I'm simply saying swap X with Y, but this 2 won't work,
because where are X and Y defined?
In main. In a different scope.
They live in this memory.
Whereas, right now we only have access to this memory.
So this is a good thing and principle for security.
We're kind of restricting ourselves to only certain chunks
of memory, at least for now, but it certainly creating problems.
Yeah.
[ Inaudible ]
>> Indeed.
So there is a solution and that is the solution.
Shhh. But we will get there.
In fact, as we introduce arrays today,
we'll begin to see exactly how we can circumvent this
and what it's going to boil down to is moving away
from just using these user-friendly labels X, Y, Z, A,
B, and actually looking underneath the hood
at the numeric addresses, which we talked briefly
about in weeks past, at how this stuff is actually implemented
underneath the hood.
Yeah.
[ Inaudible ]
>> Initially, how come I don't have declare temp as what?
[ Inaudible ]
>> In which context?
[ Inaudible ]
>> Oh, oh, okay, good question.
So up top, the function prototype.
The only thing that you have to put in the function prototype,
again, is three things; one, the name of the function;
the return value; and its arguments.
You don't have to mention any of the local variables,
because at this point in the story,
they're just not relevant.
The only thing that compiler needs to know is kind
of what pattern to look for in the rest of your code.
And if it sees S-W-A-P, open parentheses, close parentheses,
and it hopefully sees two ints inside of it,
that's all it needs to do in order
to finish compiling your code.
All the local variables can be dealt with later.
Good question.
Yeah.
>> Why does it say void swap?
>> Why does it say void too often?
>> No. Void swap, like when you're doing a void swap, --
>> So void, again, is my way
of saying swap does not return anything.
It doesn't return an int.
It doesn't return a float.
You have to with C, as with a lot
of programming language, say what you return.
And if you're returning nothing, you don't just leave it blank.
You say void and that's the convention.
Yeah.
[ Inaudible ]
>> Sorry, what about code?
>> Are scopes defined by curly braces or by functions?
>> Good question.
Are -- is scope defined by curly braces or by functions?
Absolutely, by functions,
but you can also create local scope with curly braces.
And so what I was hinting at earlier when you put semicolons
in the wrong place, and then proceed to have curly braces
around arbitrary lines of code,
you're creating an even more local scope there,
which is generally not the right intended behavior.
[ Inaudible ]
>> It's a good rule of thumb, yes.
You can find ways around this.
But a good rule of thumb is if you declare a variable, int X,
string Y, float Z, inside a curly brace,
and another curly brace, you can only use
that variable inside those two curly braces, specifically.
That's actually a really good rule of thumb.
Well, things can be fixed
by a little trick called global variables.
It's not necessarily the best solution but it is one solution,
and it's perhaps necessary --
and when we get to PHP and Web Programming toward the talent
of the semester, you will actually deliberately use what
we call global variables to get access to any forms
that the user submits, if you're actually implementing an
application, a search engine, a web-based tool,
a Facebook like tool that takes input from the user,
you'll be handed those data by variables like these.
So what can we do to solve this?
Well, let's go ahead and open up global dot c,
or you can follow along up here.
So now notice this is almost the same program.
I've got my function main.
I then print X's now such and such,
initializing dot, dot, dot.
I now assign X the value of 1.
But wait a minute, I've already written buggy code it seems.
What have I clearly omitted from main?
So there's no mention of int, and yet we've been saying
for the past couple of lectures,
that anytime you declare a variable,
you absolutely have to specify its type.
And here I am now cutting corners.
Well, not quite.
If you scroll back up on the printout or screen here,
you'll see that you can actually not only declare function's
prototypes, their general structure.
At the top of your file, you can also put variables there.
You can put a variable there,
and because it's not encapsulated in curly braces,
as we just discussed,
that essentially means it's accessible everywhere
in that file.
Any function in this file now including main, swap, increment,
cube, whatever I want to implement, now has access
to this variable X. Now that can be a bad thing.
And you can very quickly take this feature to an extreme
and start putting X and Y and A and B and 10
and all your variables up top because it would seem
to solve all of your problems and stop all of your thinking,
but it's generally not a good thing.
Because when you start writing more compelling programs
and start using libraries, other people's code,
like the Google charts API's and things like this,
if you start putting all of your variables at the top
of your file and making them global, well, what happens
if you start integrating your code with other people's code,
things start to clash very quickly, and you have to go back
to the drawing board and fix all of the collisions,
all of the names that you happen to use, like X, Y, and Z,
and Google happened to use, like X, Y, and Z,
and so just very bad things happen quickly
and so you use globals sparingly,
but how do you use them.
Well, if you declare int X up top,
you could certainly update X to one here.
If I now scroll down to the actual implementation,
now does this work or not work?
So the hint is that this is our first program that's not been
called buggy something.
All right.
So it does, in fact, work.
And yet notice that the function itself, it takes no input.
I say, void to specify no input.
You can also get away, as I said last time,
with just putting parentheses in JavaScript and PHP,
this is, in fact, the norm.
In C, the truly correct way is to be very pathantic and say,
nothing is coming into this function;
so I'll explicitly say, void here.
So this function increment takes nothing, returns nothing,
and yet it does something.
It does, in fact, successfully increment X,
because at this point in the story, X was not scoped to main.
It was scoped to the whole file.
So pictorially, it's as though there's now some other part
of the blackboard here, maybe way up here
where I can put anything I want that's accessible to main,
that's accessible to swap, that's accessible to increment
or any other function I might implement
because it is, in fact, global.
Why don't we go ahead and take our five-minute break.
[ Pause ]
>> All right.
So I've got one more piece of bad code on this point
and this is buggy five dot c. So as a comment on top
of this file challenges, what is, in fact, the bug.
Well, let's take a look quickly together.
So I start this program by declaring
as I did before a global variable X. It is global simply
because it is not inside any of my functions.
It's instead outside of them and, by convention,
at the top of the file so that I can access it anywhere, whether
or not this is a good thing, remains to be seen.
But it is a solution to this problem.
I then declare increment early on.
My prototype, again, so that I can use it later
without the compiler wondering what is this increment
that you're referring to because it's not otherwise
been declared.
As an aside, why are you able to use print F without writing
out a prototype for it?
Well, remember this line; include standard IO dot H.
When I said in Week One that you don't actually have zeros
and ones inside this header file; right?
That's not actually where someone implemented print F
and related functions, rather, in dot H files,
by convention, are prototypes.
So this thing called a prototype generally lives --
if someone else wrote code that other people are meant to use,
generally lives in these header files; whereas,
the implementation, the definition
of print F probably lives somewhere
in a corresponding dot C file.
So somewhere there's standard IO dot C,
somewhere they're standard IO dot H, but, for me, right now,
the only file I need to know about is the dot H,
because what Sharp include really does --
it's what's called a preprocessor directive.
It pretty much means open this file, standard IO dot H
and just paste its contents right here.
Now because among its contents is the prototype for print F,
that is why, very simply, I can call print F without having
to declare its prototype myself.
With, thus far, we've taken that for granted.
Now my main function here is identical.
But here's a new and improved, I think, version of increment;
returns nothing, takes nothing, but it does perform plus plus,
but I did something stupid.
I did something that's allowed, but something stupid.
So here I'm declaring another variable called X,
and this is totally legitimate because I already know
that if I'm implementing a function like swap or increment,
I can absolutely take input.
I chose not to.
I can absolutely allocate local variables.
I chose to.
This time I called it X. I hard-coded into it the value 10.
There's still another variable
in this world called X. Its value is, by default,
what did we say one, and so now there's two copies of a variable
that -- there's two copies -- sorry, there's two variables
that happened to be named the same thing,
but just as I've drawn them physically in different places
on the board, if you think of this blackboard as a big chunk
of RAM, your 1 gigabyte of RAM, your 2 gigabytes of RAM
in your computer, this version of X is here.
This version of X is here.
And that's fine, because inside
of curly braces can you redeclare variables
with the same name if you intend
to quote unquote shadow the previous variable.
Now for now, its hard to argue that this is a good thing
but it's a common thing.
It's a common mistake to make if you forget
that I've actually declared that variable up top,
but wait a minute, I know any time
that I use a variable, I have to declare it.
Well, this will, in fact, be declared, but, unfortunately,
you're using a different chunk of memory.
You're incrementing this chunk of memory.
It's plus, plus to eleven.
You do the math correctly, increment returns.
What's the value of this X at the end of the day?
It's the same.
It's still 1, because you plus plussed the wrong symbol called
X. So for now, take-away from this, don't do this.
We'll see that there's actually compelling use cases
for using the same names of variables
in different context's.
Frankly, you'll see a matter of design
or style sometimes just makes sense to call the variable X
if that's consistent with the type of code you're writing
or maybe just to come up with an arbitrary example --
maybe if you have to parameters and you want to call them left
and right because, conceptually, in your mind,
the purpose of this function is to do something
with the variable that's on the left-hand side in the world
and a variable that's on the right-hand side.
You don't want to rename them L and R or X and Y
because you want to call them left and right.
Well, you can but you have to appreciate the implications
of doing so is the take-away here.
So what's really going on inside of memory.
I've been using the blackboard a little ad hoc here,
but suppose I neaten things up here now and present
to you this rectangle that's going vertically,
this rectangle is let's say R RAM,
the memory inside of your computer.
This is different from the hard disk, which is where files
and stuff are permanently stored.
RAM is this memory recall or, as you'll soon find
in problems Set One, that's used for ephemeral purposes.
When you double-click a program, it's loaded into RAM.
When you're working on a file, it's saving constantly to RAM
but also hopefully to disc, the hard disk
so you don't actually lose it if the power goes off.
Well, if this is now my RAM, what's really happening is
that there is some organization to functions
in such being called, by default, if this is my RAM,
main excel can have parameters, as we'll see in just a moment.
Arg C and Arg V, those symbols I've been waving my hands at,
well where are they located in memory?
Well, memory is this rectangle, by default,
they're located at the bottom.
Now they may not take up the whole width.
This is somewhat of a artist's rendition,
but they're at the very bottom of my RAM.
Now what's on top of that?
Well, if main has any local variables X or Y or temp or foo
or bar, or whatever the case may be,
those variables come next in memory.
So you can think of it as left or right, top to bottom,
or whatever, the point is they come next in RAM.
Now if you call a function, like increment or cube or swap,
or in this case, foo, those variables are the parameters
to that function, end up getting stored next in memory.
So everything is literally going back to back to back and so foo,
similarly, if you have any local variables,
like temp, it then goes here.
So when I said earlier that as soon as swap returns,
all of the memory allocated for swap is now useless.
It just disappears.
That's because this process on roles.
If you think of these kind of like trays in a cafeteria,
right, that are kind of upside down, and by default,
they're stacked from the floor on up and up and up.
Well, if you want to call a function,
it's like putting another tray on that stack of trays
and that tray represents a chunk of memory that,
that function can use.
Well, if that function calls another function,
you put another tray on, and so that new tray represents
that function's chunk of memory.
But as soon as the most recently called function finishes
executing, you have to take that tray off the stack in order
to get at the previous function's memory,
and once he's done executing, you have to take that one off
and then what's left well then main.
So even though we're not literally throwing RAM away,
we're not physically moving anything, conceptually,
we have to go through memory in this order back to back
to back and then undo it.
So pictorially, you can imagine foo getting called
and then it finishes running; so these rows
in this chart will just be whisked away.
The bits are still there, much like bits are still left
when you erase a file on your hard disk
but they're forgotten about.
So pictorially, this row would simply disappear.
Now there's a bigger picture here.
I intentionally used this very common analogy of a stack
of trays in a cafeteria.
Well, because the memory we've been using for local variables,
and for functions, storage space is what computer scientists
generally call the stack.
It turns out that slightly before the stack,
slightly before this conceptual chunk of memory,
there's other things called environment variables
that we may see over time but elsewhere
in memory are other things.
Text is where the zeros and ones
that compose your file are actually stored.
So when you compile a program called A dot out, or skittles
or wherever, and you double-click that program,
or our in our command line environment,
run it with dot slash skittles, that program is loaded
into memory just like Microsoft Word
or whatever would be on your own computer.
Where is it put in memory?
Conceptually, it's put at the top of my chunk of RAM,
below it, goes initialized and uninitialized data --
this is a fancy way of saying global variables come next --
and below that, comes what's called the heap.
So before long, we'll see, especially for problems
that we can't allocate an int every time we want
to store something, because what if we want
to store 140,000 English words.
Right. We're not going to have 140,000 variables in my program.
I need access to more memory, and I need it fast.
Well, there's a chunk of memory called the heap
that you can grab as much memory as you want so long
as it exists for your program.
But there's kind of a problem here.
And this picture kind of makes clear
that we're headed for disaster.
Right. There's only a finite amount of memory.
And very deliberately has that memory been laid out as such.
So what's the problem?
We're probably going to run into very soon.
Right. Stack.
Stack. Stack.
You're calling functions, functions, functions,
but you're allocating heap, heap, heap,
heap memory for your words.
Eventually, stack and heap will collide.
And one of the ways you can make a program crash, intentionally
or not, is to essentially use up too much memory
or call too many functions and what happens is, bam,
one hits the other and bad things happen.
And, in fact, let's see --
don't do this at home or on our systems --
but let me go ahead and do nano don't do this dot C. Let's go
ahead and do int main void.
Let's go here and let's go ahead and say let's call this foo
and what I'm going to do here is void foo -- foo, incidentally,
is a stupid word the computer scientists use
when they just need a placeholder,
mathematicians say XYZ, we say foo, bar, Baz, clucks,
and then it goes on from there, you'll pick up on it.
Void foo. All right.
It's appropriate to make fun.
So what if I do this.
This is kind of trippy.
Right. So main calls foo, foo is declared, but wait a minute,
I need my prototype; so void foo, void.
I just do a copy paste of that.
Now there's a whole lot of foo and a whole of void here,
but this is consistent with the lessons thus far today.
Main calls foo, foo calls foo.
This is a problem.
Right. Just conceptually, there's this kind
of a funky picture that never seems to end.
So let's see what actually happens here.
I don't even need standard IO
because I'm not printing anything.
I'm really just messing around with the computer.
Let me go ahead and make, don't do this.
Looks good.
Okay. Literally, don't do this.
Bad. All right.
So segmentation fault.
Some of you have actually had the privilege
of having these errors already, for different reasons.
You probably weren't calling foo ad nauseam here
but segmentation fault refers to segments of memory colliding.
Two pieces of memory actually touching each other
or you touching memory that you don't actually own,
in which case the computer doesn't really know what
to do and just, bam.
It terminates your program.
And what very often happens if you do an LS in your account,
to list your files, there's a whole lot of stuff in here
at the moment -- and I don't have it here
but what you'll often see -- I'll just fake this demo --
is a file called core.
If you ever see a file called core or something similar,
that generally means you made a bug, and it's a pretty bad bug,
and inside of core is we'll eventually see the contents
or some of the contents of the computer's RAM
at the moment your code screwed up, which is actually useful,
because soon we'll start using a debugger, a diagnostic tool,
where you can kind of do like an autopsy of your own program
and see what was inside of it
at the time this error actually happened.
So now let's actually put some of these ideas to use
in a more familiar way.
So I've used this jargon before; command line arguments,
but what does that really mean?
Well, anytime you run a program at the command line, like nano,
you've almost always been putting one or more words
after that program's name; nano hello dot C, GCC hello dot C,
and any number of MKDIR for make directory,
and then peace at one or similar.
So all of these programs or commands
that we've been using thus far for the piece set in class,
take what we call command line arguments, they are the zero
or more words that follow the program's name.
Well, thus far, I haven't written any programs
that themselves take any such arguments, and yet it turns
out I can do exactly that.
If I don't write the shorthand notation int, main, void,
but it explicitly says, you know what,
my version of main is actually going
to take some command line arguments,
and I want to call them by convention Arg C, and Arg V,
I can actually access input from the user without using get int,
without using get float, without using get string;
I can get it directly
at the blinking prompt, the command line.
So here's a program called Arg V, this is fancy speak
for argument Vector, a list of arguments for the left or right.
I have declared main as, int main, as before.
Now finally, I'm going to do something
with this crazy syntax.
Inside the curly braces is this program's code, what am I doing?
I'm actually just going to do something simple first,
print the arguments to this function.
I print F, I backslash N, just to pretty up the screen,
I then iterate from, I equal zero up to Arg C;
so Arg C is the convention.
You can call it foo if you want, but you shouldn't.
By convention, it's Arg C, because it means argument count.
How many words were typed at the prompt, by default, Arg C,
should always be at least one.
Because even though it's a little confusing
or a little sort of contradictory,
the argument count includes the name of the program itself,
which can actually be int useful because if someone --
if a producer changes the name of a program by renaming a file,
you, the program still have access
to your own name by this mechanism.
Now what's this.
Well, a while back I said that we'll use it at least
for a few weeks this moniker string.
A string is a data type.
Doesn't really exist in C. It only exists in CS50's library,
but I then revealed that this is actually the word string is
really just a synonym
for a slightly more interesting syntax of char star.
A star is a preview, is referring
to what's called a pointer, similar in spirit
but more dangerous than references in Java
for those familiar, but we'll soon focus on these next week.
This really is just a way of saying this is a string.
The square brackets here, meanwhile,
say this is a special type
of variable that's got multiple values inside of it.
So thus far, when we've defined -- declared an int and a float,
and so forth, we just put one value in there, the number 2,
the number 3.14, just one single value.
But we said earlier that, you know, we're going to get
to the point where we want to have a lot of pieces of --
a lot of variables in memory, maybe 140,000 dictionary words
for some future peace set, but we don't want to enumerate line
by line by line 140,000 variables.
It turns out you can list one, give it a name,
and if you use square brackets,
that tells the compiler I actually want
to put multiple values inside of this -- inside of this variable
and how do we do that?
Well, we'll see right now.
So this four loop is pretty familiar.
Arg C is just an int; so this line
of code here should be pretty comfortable by now.
Just iterates from zero
to Arg C. The indented line here print F is clearly printing a
string, as per the percent S, but what is it printing?
Well, the bracket notation means you can index
into this variable.
You can think of this variable Arg V
as literally an array a sequence of chunks of memory
that literally are back to back to back in memory,
and when you say bracket zero, by convention, you are referring
to the variables stored here.
When you say bracket one, you are storing --
you are referring to the variable here, bracket two.
And how about if the array is size N,
and I say bracket N, where am I referring?
[ Inaudible ]
>> Too far.
Right. N is over here for counting from zero.
So this 2 is going to be a common mistake.
Last time I alluded to the exploit in the game Zelda
for the Wii, where people were taking advantage of this
and compromising the Wii system
and installing their own software.
It pretty much boils down to something simple as this.
That game uses an array for something,
maybe Zelda's inventory or something like that,
and the programmer who wrote the relevant line of code,
didn't check that the other functions are allowed --
didn't check how far into this array other code is allowed
to index into; so somewhere
in Zelda is probably square bracket notation
where it's bracket N, instead of a maximum of N minus 1.
So when we count, generally, again,
we start from zero, we go to N minus 1.
If you ever try to go beyond the boundaries of an array,
as we'll soon see, bad things happen.
So now what are we doing here?
I'm first printing the zero argument
which I said is the name of the program itself.
I'm then printing bracket one, bracket two, bracket three,
bracket dot, dot, dot up until the total number of arguments,
whatever that may be, and it's going to be at least one
because the program always has a name.
So let's go ahead and compile this.
Make Arg V1.
It seems to run okay.
Now let's run Arg V1; enter.
Not all that interesting but there's
that new line I promised.
There's the name of the program including the dot slash.
Well, let's make this more interesting, foo.
All right.
Slightly more interesting.
Bar, slightly more interesting.
Baz, now it's going to keep doing this ad nauseam
until I hit some kind of limit.
But for now, it will pretty much go up forever.
But bad things will start to happen
if I don't mind this lesson of indexing.
If I do this, which is kind
of a mistake we made last time, if deliberately.
Let me re-save this.
Recompile my program, and now rerun Arg V of foo and bar.
Okay. So that's already some badness happening.
So why is that happening?
Well, again, just as I said verbally a moment ago,
if you're going here, you're literally touching,
trying to read or change memory that's beyond the boundaries
of a chunk of memory that you're supposed
to be touching based on its length.
And in this context, the length of that array is stored
in Arg C. Well, let's take a look at a slight variance
of this that reveals further what we can do
and reveals what a string really is.
So here's a program set
up in the same way, main looks the same.
I'm again, saying print argument's new line.
I'm again, iterating with this four loop, same code as before.
The only interesting thing now is a nested loop.
So when scratch blocked terms, I'd have a four loop
or like a forever loop or something
and then another one inside.
Same deal here.
The curly braces ensure
that everything is logically clustered where it should be.
Now what am I doing?
I'm iterating on the outside from I to Arg C, zero to Arg C;
on the inside, I better not use I;
otherwise bad things are going to happen.
If I'm iterating from I on the outside, I on the inside,
I'm going to start changing the value
and I might very well induce an infinite loop but J is okay.
So notice what you can do.
We've not seen this trick before,
at least, not in lecture.
For int, J gets zero, we can do that.
Thus far, we always put what after the zero?
In every example thus far we've had a semicolon saying that's
our initialization.
You can actually initialize multiple things at once
by separating them with a comma, and this is sometimes helpful.
It turns out there's a new function
that you probably have not used yet called strlen, S-T-R-L-E-N,
programmers early on and still like to be succinct
but communicates sufficiently what they mean.
So strlen is the length of a string.
Well, Arg V bracket 1, is, in fact, a string.
Because I've said that char Star is really just the true version
of this.
So conceptually, what is main being handed?
It's being handed an array of strings.
It's being handed a picture that looks like this, and inside each
of these squares is a word foo and bar and baz as well
as the program's name.
But here, I'm just being a little more pedantic,
that's really what a string is.
We'll see why before long.
So if Arg V just contains a whole bunch of strings, surely,
using this new square bracket notation,
can I go to this string or this string or zero or one or two
or three, but you know what, I want to know the length
of each those strings, thankfully,
someone else wrote a function called strlen,
that's given a string, given a bunch of squares like this,
whereby, each of them contains -- given a string -- sorry --
let me retract that, given a string, Arg V bracket one,
it tells you how many characters are in it.
If I type foo, I'll get back F-O-O.
Now here's the semicolon, J less than N, where N is this, J plus,
plus; so what am I doing?
Well, turns out that with arrays,
not to make this too trippy too soon,
but Arg V bracket something is a string,
you can also use square bracket notation to go
to a specific letter in a string,
because little teaser a string is just an array.
When you've been typing in words to the keyboard like your name
or any word that you're trying to provide to the user,
a string really looks like this.
Is it a character of eight bytes -- sorry --
eight bits, eight bits, eight bits,
and I've done the same picture on the board.
So if a string is actually implemented as an array
of characters, much like Arg V itself or arrays in general,
are just implemented as array of strings, well, so can I iterate
over each of the arguments as I did a moment ago,
but then also each of the characters
in each of the strings.
So Arg V bracket I, gives me the Ife string that I typed in.
Arg V bracket I bracket J, gives me the J character
or letter in the Ife word.
So that's all we're doing, picking a word and we're homing
in on a specific character.
So what's the end result.
Well, notice I'm calling print F with percent C,
and then I'm printing out each of these letters one at a time.
Let's go ahead and make this.
So this is make Arg V2.
Let me go ahead and now run Arg V2 with nothing.
Well it's a stupid looking program,
but because I had more new line characters,
and because I was using percent C, for individual characters,
one per line, now I'm seeing dot slash ARG V2, well,
now if I go ahead and rerun this with foo,
I get this effect as well.
So for now, a string is really just an array.
It's a picture that, again, is literally like this.
Somewhere in memory, back to back to back or all
of the strings and with them can we store actual words
and phrases.
Now why is this actually useful?
So now that we begin to have this ability to express strings
in memory, to understand what they are, we can start
to apply actually real-world algorithms to them.
So does anyone know or recall what this says?
This is a sentence or string phrase that has been encrypted.
It's been encrypted pretty naively, pretty simplistically,
but it's actually an English sentence that's been somehow
scrambled; but scrambled in a reversible way.
If you just scramble a sentence, it's pretty useless
because the recipients are never going to be able
to reverse the process.
So there's a pattern here.
Think back to a movie's that's on TBS, ad nauseam,
in December called Christmas Story.
Anyone? Little Ralphie.
[ Inaudible ]
>> Yes. Be sure that's one of two of us have seen this movie.
Be sure to drink your Ovaltine.
So Google it or look
at the Wikipedia article for this movie.
But in this movie, the kid gets a little secret decoder ring.
It looks a little something like that,
and the screen doesn't quite do it justice here,
but there's two alphabets; A through Z, and then A through Z,
but the inner A through Z is on a small --
it has a smaller diameter; so it's a ring of letters.
Outside of that are the same letters but slightly wider
and the whole thing roates.
So if you had A here, you can rotate the outer disk
so that the A lines up, not with A,
but B or C. So what you're seeing here is a very simple pop
culture reference to something generally known as a Caesar site
for a drive from Julius Caesar, who, purportedly, years ago,
used to send in encrypted messages using precisely this
fairly simplistic mechanism; whereby,
you take a message you want to write you then scramble it
by rotating conceptually every letter by probably more
than one place, but fewer in English than say 26 places,
lest you be doing no work at all.
You rotate the letters by a deterministic amount,
by a fixed number of steps
so that the end result is actually something
that can be reversed.
The number that you choose to rotate your letters
by is what we call in cryptography, a key.
It's a secret number so that
if Julius Caesar scrambled his message with the key 13, well,
then the recipient had better know what that number is
or realistically, -- and this is why it's kind of hard to buy
into some of these age old algorithms, --
what would an alternative approach be to figuring
out Julius Caesar's messages to his generals if he didn't know
that secret number was 13?
So it's a trial and error.
You can brute force it and unfortunately,
the so-called Caesar cipher is not very secure
because if you assume, for our purposes in English alphabet
with 26 characters, say all lowercase for all uppercase,
my God, you only have to try like 24, 25,
26 possible rotations until you can figure
out what his secret message is.
So there are more sophisticated approaches,
some of them are mechanical.
Those of you with backgrounds in history or we've seen --
or remember World War II with technologies that were used
in it might know of the Enigma machine,
which is kind of the same idea.
You type at the keyboard words that you want to encrypt.
So something the Germans used on their U-boats and the output
of that is a scrambled message.
Here, the secret is not a number 13, it's actually the build --
the diagram, the details, the gears, and the handles inside
of this physical machine that constituted a secret.
So one of the things that the Allies very specifically wanted
to do in World War II was to hijack one of these devices,
take it from a U-boat because if they had this physical machine,
certainly can they start decrypting then the
German messages.
They don't have to know something in this case.
They have to have something in this case.
So in general, both of these are examples
of what we call secret key crypto.
This little picture here offer some jargon.
If you have some plain text, some message that you want
to send, well, you can encrypt it
or you can scramble it using a key, a secret key,
which might be a physical machine like the Enigma
or it might be a number like 13.
But the catch is that the party on the other end of things has
to have that same machine or know that same number.
But this is a huge problem.
Right. Because all of us have probably bought something
on Amazon.com or the like, all of us have probably logged
into Facebook.com, passing your credit card information
over the Internet, passing your username and password
over the Internet, and as you probably know,
as a casual user, https denotes secure.
There's cryptography going on.
But how many of you have ever called Facebook up
or called Amazon up and kind of whispered
into their ear I'm going to encrypt this with the number 13.
Right. So you have this -- it's kind of a stupid thing.
Right. If you're doing that, it's a little strange.
But the point is that how is Facebook,
how is Amazon possibly going to communicate securely with you
or your laptop using cryptology if you both have
to know the same secrets.
Well, this is a problem that we have solved
and will solve in the weeks to come.
See you Monday.
[ Silence ]