 All right, and we are at pointer analysis. Any other questions before we start? You said not looking at the class? Nope, nothing? OK, good. OK, so really parts of semantics, right? It worked. Sorry. You guys can't see that. My spring home to presenter mode was amazing. This hasn't worked literally all semester. Nobody's touched anything. Awesome. All right. I can see what's happening in the future. It's like a super bubble. OK, so we talked about assignment semantics, right? And we went through very, very specifically what assignment semantics mean. When we see x equals y, we now know very precisely how to say what happens, right? When we see x equals y, we want to copy the value associated with y to the value associated with the location. The value of the location associated with y to the location associated with x. Cool. So we saw this. We saw what's there between l value and r value. Also, do you have a right value? Or do you have a right value? Or do you have a right value? Yes, so l value has a location associated with it, right? It is a place that you can put. In our circle box diagrams, it's going to be a box. L values have a box associated with it. r values do not. r values are just value, right? Like 5, or 5 plus 10, right? The result of 5 plus 10. Cool. All right, now we get to pointers. Everybody's favorite. How many of you are using pointers in project 3? Yeah, how many of you feel like you know what pointers you're doing in project 3? That's 80, 70%, 50%, cool. OK, so now I want to learn what the semantics of the pointer operations actually are, right? And first, before we do that, I kind of have to go back and maybe change our box circle diagram here. So we're going to have a box for x circle with some kind of value in it. What's missing from here? The value of x inside the circle. But here in this example, we've never given x a value, right? So we don't know what to add. It could be anything. Let's say it's a question mark. The what? The location. What about the location? I got the box. The box is the location. Yeah, but the box doesn't mean anything. The address. The box means whatever we mean. Say it again. Which piece of silicone, which respective material is living on? So how do you refer to this box? Well, normally, right here, we can talk about x, right? So but we do know that this box is not just some abstract thing. It actually lives somewhere. So this box itself has a name, or we can think of an address. What's that? x refers to the box. We refer to the box as x with the variable, but the box itself physically lives in memory and has some address. It's going to be 0, 2, 2 to the 32, 32-bit system, or 2 to the 64 and 64-bit system, right? But we can think about it abstractly. So we can think about it. We can say that the memory address is just alpha. And so what we'll do is we will, in the future, we're going to put the address of all the boxer diagrams here on the right. So usually, we'll just use alpha or beta, right? Because we don't actually care what the system gives that memory address, right? It could be 10, it could be 20, it could be 100. It doesn't really matter to us, right? OK, why is this important? Well, for pointer operations. So what does the address of operator do, in terms of address of what? Can you only apply the variables? Objects, structs, what's the difference? Where's the address of an L value? It returns the address of an L value. Yeah, so an expression, right? It could be anything. So what it takes in, it's, unary operator takes in one parameter and returns one thing. And think about input types, right? It's really just a function. You can think of it as a function. It takes in L values and it returns an R value, which is the address of that box. That's all it does. The result is an R value, and we even know the type of that result, right? The type of that result is T star, where T is the type of the operating, right? So if you have an integer x and we do the address of an x, what's the return type of that? It said what? Int star, and it's also an R value. So can it be on the left-hand side of something, right? That's pretty much the same thing. Like it essentially returns 5 or 10 or whatever that memory address is. So it doesn't make sense to talk about the address of x is equal to 10, right? Assign the address of x to be 10, because specifically it's an R value. OK, and this is what we already said. So this value is the address of the location. So every location has an address associated with it, and this address of operator is going to return it. Cool. It's pretty easy. So what's the opposite of the address of operator? The dereference operator? Why is it the opposite? It's the same thing. It's a circular definition. Why does it do the opposite thing? What does it do that makes it the opposite? It goes from that L value to this value. Yeah, it goes from R value to address, right? So it's input type is either an L value or an R value, just like the right-hand side of an operator can have that. But it returns an L value. And what specific L value does it return? OK, yes. So for types, it gets rid of the star operator. So when we use dereference on an integer pointer, the return type is an integer. But what is it actually returning? And it stores the right-hand side of the R value. Not the R value, the L value. It returns the where can you use a pointer, a dereference operator, sorry. Right-hand side. Can you use it on the right-hand side? Can you use it on the left-hand side? Yeah. Yes. Yeah, so that means it must be an L value, right? We'll see exactly why. But well, why is because that's how it's defined. So it takes in one parameter. It can be applied to either an L value or an R value of some type T star. And it returns one kind of site. T, yeah, it's all pointers. Just get rid of these types, right? So the int star star means it's a pointer to a pointer to an int. If we dereference that, we would get an int star, a pointer to an int. Cool. So let's look at this. So let's say we have some int, some x, right? So our box circumsigrams are just going to look like this, box circle, right? Super easy. And let's say there's x, v inside there. We don't know what it is. We just created x, some kind of value inside x, right? So this is going to break everything. Can you all see this? People in the back? So I have int x and int y. I want to know what are these values? What is the box circumsigram for this look like? So I know when I see x, I have an x that's associated with, that is bound to some location that has some value. What's the address of x of this location that's associated with x? We don't know. Let's call it alpha. Doesn't matter. Somewhere, right? But we know it has a distinct location. We just don't know what that is. Then when we see this next line, int y, do we also know anything about the value inside x? Not yet. No, not yet. So now I'm going to do another box circle diagram of y. So y has a location associated with it. Does it matter when I draw this box circle diagram that y is an integer pointer? No, we don't care, right? It doesn't affect, that's just the type of whatever is inside y, right? That doesn't affect what? The fact that the compiler is going to allocate a location and bind it to the name y. What's its memory location? Beta. Oh, beta. Cool. Then I get to this line, x equals a 10, yeah. But does y have a degree associated with it when we declare it because we haven't allocated the memory to it? When we declare it here? Yeah, because we have the value of the value of it. Let's make it a little bit more explicit. So, is it in x, right? So the compiler creates a location for x automatically. We'll see exactly how this happened. This is happening on the stack for right now. But it's a local variable. It has to put x somewhere, right? So on this declaration, after this declaration, we can assume there exists an x. And it exists somewhere. We don't really care where, so we'll call it alpha. And we know that it doesn't have a default value. No, the C semantics does not say anything about that, right? There's random junk in there right now. Cool. So against the int star y, what's the difference between this and this? Does it, though? What is it underneath the hood? Yeah, it's just four byte integer, right? Just like an int is what? Four bytes, right? If you do, you can check this yourself. You can write a quick C program and print out. Use printf to print out what is the size of an int versus the size of an int pointer versus the size of an int star, star, star, star, star, star, star, I don't know what you want, right? So it takes up four bytes of space. So we actually do know, let's say, the size. We could know the size of this box, but for right now, we don't really care. But we know that when we see this, it's a local variable. So it has to allocate space for y, right? It has to be there. Otherwise it can't store these addresses anywhere. And so it's exactly the same as x. It's just a box, it's a location associated with y. Does it have a default value inside of it? No, no default value. And it just has some address, beta. That's it, that's all we know. We'll get into how malloc plays in later, but. Right now, y doesn't need to be malloc at all, right? Because y itself just exists, right? Y is a variable just like x. It needs to exist, it needs to have four bytes of storage allocated to it. Cool, then we get into x equals 10. So then what does this do for our semantics? Copy what? So put some value in an x. In x, right here? We gotta be really precise, what's the most, well, what's a very precise way to say this? Put the value of 10 into the address that x refers to. X, so close. So address is here, right? Yeah. Do we care that this is alpha versus beta, right? We only care about the address of x at this point, right? The compiler has bound x to some location, right? So it's in a location associated with the variable x, right? So we wanna copy the value 10 into the location associated with x. This is part two's one. Very similar, just slight. This is why it's definitely my favorite part because we have to be very precise when we talk about these semantics, right? Cool. Okay, now get to here. What's the first thing that happens? Yeah, the first thing that happens we have an expression on the right-hand side and we have, we have an L value and R value on the left. L value should never have an R value on the left. Tip one. Okay, so we have to, so then what, as an expression, what is the expression address of an x return? In general, what's it gonna return? An L value and R value? P star. An R value, and what is that R value specifically here? Alpha and alpha. Alpha, it's gonna return the address of the location associated with x, right? So it returns alpha, which is an R value, and then so then what happens with the assignment semantics? Copies of where? Copies of alpha to the base of y. Copy alpha into location associated with y. This is all pointers on it. So the only thing that's different than a pointer than a normal integer, right, is that a pointer stores an address and integers store integers. Addresses are integers, right? So now what happens if I do something like this? How do I do that? Let's do star y equals, wait, where, two. Star y equals 42. So what I have on the left-hand side here. I have dereference y, so that's an expression. What is the expression dereference y return? L value or R value? L value. L value, there is a location associated with that. And so the dereference operator, essentially what you can think that it does, it takes whatever, it takes in an R value, it takes in whatever, so in this case, we do take the value that's inside the location associated with y, which is alpha, look up and return a location that has that memory address. So star y is gonna return what location? The location with the memory address alpha and the name x, right? So on this diagram, we can say that this actually points, you could say here, right? I'm being super precise here, that it actually is pointing to the box itself and not the value inside the box, right? Because the dereference operator, so this we could label this as star y. So star y equals 42, so what does that mean? Into which, so copy 42 into which location? The location that's associated with x and also location associated with star y. Time and point are so easy, right? Maybe. I don't know if I did this. Is that valid? What's the type of y? Type y is in star and address of y, what's the type of that? Instar is the star as well. Instar, right? Oh, you're right, instar star, this is not working. I put the address up like a star and y. Well, here we go, silence your compiler for your students. We'll say we'll cast it. It's fine. Yeah, we'll do it, right? Cool. So the casting is really just for the type system, it doesn't have any impact on what's actually going on, right? It's the same thing that's going on. So I'm taking the address of y, what is that? And what am I doing with beta? I'm putting it inside which location? The location associated with y. So now does star y point here, right? Star y is an appointment here, that's normal. Okay, we kind of already saw this. This is how you can think of the dereference operator, right, is it points to whatever location has the address of the value inside. So this is why, on a similar note, if I did this, can I do this? Is this valid, syntax and semantics? Ignoring the type system? Don't know, still asleep. So what happens here? So what's the difference between these two lines? What's the semantic difference between these two lines? In the second one we are... So here it's a constant value of 10 and here it's using the address of operator. Then what's the difference between this line and this line besides that it's star? What happens here with our circle, box circle diagrams? So what's gonna happen here? So is there any difference as to what happens at this line versus this line? Other than type stuff, which I just got rid of by casting. I'm telling the compiler, trust me, I know what I'm doing. Right? So then what happens? 10 go inside where? So this says copy 10 into the location associated with Y. Did I bring any rules by doing this? Yeah, now the question is, well, it's not talking about that yet, but... So can you do this in your programs? Yes, you absolutely can do this in your programs. Right, it's just a pointer. A pointer, like we said, just has four bytes that means something when you use the dereference operator because you're trying to look up a location that has the memory address of that thing. But you can do this. You can copy in a pointer is no different, well, under the hood, no different than a regular integer. So I can do this. Then what happens if I try to do... What happens if I try to do Y star? Let's say X equals Y star. Nope, it'll just do this. It looks like I trust you that this 10 is actually some kind of end pointer. So I will copy that value 10 into Y. So what happens if I say X equals Y star Y? What's it gonna try to do? Yeah, it's gonna try to find some memory address that has a location 10 and it's gonna try to return this box. What happens if your program does not have memory address 10 allocated? Segmentation fault, yes. One of the most common cases of segmentation fault is when this has, except what is null, really? Zero. Null is literally just a macro for zero. And then, so when you try to dereference a pointer that has zero as its value, what does it try to do? It tries to look up an address zero and tries to return that box. And on, I believe, almost every system null is not mapped. So this will cause a segmentation fault. So this is why you get a segmentation fault when you try to dereference a null pointer. Now, this is a lot different than Java, right? Because Java tells you if you have a null pointer exception where a C is just like segmentation fault. It actually assumes you have all this background knowledge of pointers and memory addresses and memory mapping and segments and all that stuff. That's just the way it is. It's a fun example. Okay. Yes, so where do you saw L stars and X, star X, sorry, dereference X is an L value, right? So we saw that star X returns a box. I don't know why I have this arrow yet. Yeah, we saw that, blah, blah, blah. So we saw star X equals a hundred and looks up the box associated with star X. In this case, the box of location X, V and copies the value 100 into there. Really wanna believe. So now we start to get weird. So this is all you need. This is all you need. You've learned everything you need to know to master crazy complicated pointer operations. This is it, right? It's kind of, you know, I want you, I think you have to internalize this fact that under the hood, these things, pointers are no different than integers, right? Under the hood, they're just a place to store and address. That's it. And then when we dereference that, we're pointing to and then trying to access the location where that address that we have inside the value of Y which is kind of way more confusing than I think it is. That's not what I want you to do. Okay, cool. Let's go with this. We have int X, int Z. Let's say Z is equal to the address of X. Can we do this? Adress of X returns what type? What is the address of X return? Type. Type. What is T? Int, instars, right? The input type is an int. So the output type is an int star. So normally the compiler would yell at us but we're saying, no, no, don't worry. These four bytes that you thought were an int star are actually just an int. So is it gonna do this copy for us? Yeah, just like any other integer, just like X, Z equals 10, right? Oh, okay, that's what that came from. Thanks for peeking a little bit. Right? So here if we have, if Y is the address of X, right? All this line does is copy Y into the location associated with Z. Now we do things like star address of X equals to 10. What does that do? How do we de-pack this? Is it valid, first of all? I'm taking the address of X, and then we have to bring the value into the box. Talk to me about L values and R values. So is the assignment statement? So we have an assignment statement. What does that mean for the L values and R values? What do we have to have? We have to have what, where? Passing L value on the left side, right? We know that. Passing L value on the left side, what about the right side? It is an R value, right? And is that valid from our assignment semantics? We've seen that that's okay. Cool. So now our constraint is the left side better be in all L value. So we start where? The outside in or inside out? Inside out, just like the operations are gonna occur, right? So what's the first operation that's gonna occur? Address of X. Okay, can we take the address of X? Yes. Yes, what does it return? What L value or R value? What does it take in? What does it return? Takes in an L value and returns what? R value. An R value. And so the star of that takes in what? Value or L value and returns what? L value. L value. So at the end we get out an L value. So then what is this? So look at this at the box circle diagrams, right? Because we need to know what is this location on the left hand side? Where do we actually put 10, right? So we take the address of X, what's the address of X? And then we, but just Y, right? Y is a value, Y is not a variable at this point, right? Y is like our alphas, right? It's just the address of X. And then we say, so what does star Y do? Your reference is what? What does D reference mean? There's nothing in Y, Y is a value. It looks up the location. It says what location has the address of Y? Which location has the address of Y? The one also known as X, right? This top of the box. And then, so where are we putting 10? Into the location associated with X. So could we, another way to think of this, could we flip the star in the ampersand? Because an R value returns an R value. Because the ampersand returns an R value, and we can have an R value on the left hand side. Can we do X is equal to star address of X? So what do we have on the left hand side? An L value, what about on the right hand side? An L value, so same thing, right? What does address of X return? Y? And D reference with a value of Y looks up the location that has the address Y, which is right here. And so we copy 10 back into X. It's easy when you have fully understood exactly what these operations do, right? But even if it's not easy and you're not at that point, you can still just step through exactly what's happening at each thing and say, where are these values moving? Yeah. Is there any fundamental difference between that last line and just the statement X equals X? Nope. Well, more, was it something you said, two C to U cycles problem? More work, and more work for you in your brain. I wonder if there's some, you could do it, I think as much as you want. So the next thing would be parentheses and incrementing the right hand side of that, and where, which incrementation gets applied when? Yes, that would be something I would never ask you to do, because I think it's silly, because it's a bad practice anyways, using inline increment and prefix and post-fix incrementation. It's too hard to figure out what exactly you mean, so you're expressing yourself very poorly. To me, I always, if I use it, I put it on one line by itself, John. That's way easier to understand, but I really make me want to do something like that, but I won't. OK, let's look at the crazy code. Ah, here, we've reached a fun exercise. OK, so before we do this, I need bigger font sizes. Oh no. I almost just shut off my computer. I don't know why that button exists in this right now. Let's see, I want format font. Bigger, yes. Like how it doesn't tell you what size the font is. It's bigger now, cool. So we see a declaration. What does that mean we know in terms of box circle diagrams? We have a box for what? X, we have a box, and we know that there's a name bound to that location, X. What's the address of X? Do we know what's inside X? Nope. All right, so what is malloc? What does that mean? Do a new box. Yes, malloc is a box generator. What's the arguments to malloc? How many bytes do you want your box to be? How big of a box do you need? Why does it need to know that? Yeah, so should you ever have a case where I have a completely separate box, let's call it Y, that also has the address alpha? Would this be good for my programming language? No, I would never want two of my variables or what would be worse if this is four bytes and this is like alpha plus two. So they only share two bytes of overlap. That would cause an insane problem if you're never going to figure out it, right? And so malloc, make sure, and we're actually going to, I think we'll have time in this class to look at how exactly does malloc work and how does it actually do this and how does the heap work? But for now we can think of it as we tell it how many bytes and it returns as a box of that size. But what does it return? Does it return the box? That's the first one, right? The address of that box, yes. So it returns a box, it has some address that's called beta, right? What is the size of it? Now what is the size of it? What was it? It's a keyword. It's a keyword? That does work. Who determines the size of the status? Who determines that? Do you get to decide? Operating system, the hardware, what was that? The compiler, right? The compiler has to decide. It needs to know when it creates X, how many bytes do you actually want for X when it compiles this, right? It may, and so for an integer pointer, so an integer pointer needs to store what? Add addresses, right? How many addresses are there on a 32-bit system? Who do the 32, how many are 64? Who do the 64, can you just take a 64-bit application and run it on a 32-bit operating system? CPU? No, right? Because the compiler specifically generated code to take advantage of, specifically said, hey, I'm compiling this, and you can actually, with the dash M flag of Linux, you can specify which, if you want 32-bit or 64-bit. So you can tell it, and then based on that, now it knows, okay, this means an integer has four bytes, so then it knows that when you see size of int, it substitutes in four, so there's actually no function call here. So there's a function call, right? So we have an expression. So I have on the left-hand side an L value and R value. L value, it wasn't quite as unanimous as I looked for. And then on the right-hand side, what do I have? Which is what? An R value. So what does this do? So now, size of int, when I call it this first time, it returns beta. So now what happens? Still close. Copy the value beta in the location associated with X. Dresses are the things to refer to locations. So after that line executes, we'll have beta here. And now, when I see star X equals 100, what location does star X refer to? The location with address beta, does it have any other names? Well, star X, yeah, right? So I know star X is here. And so when I say star X equals 100, what am I doing? Yeah, so copy the value of 100, there's two ways to say it. Either the location associated with star X or the location with memory address beta. So this is all you do when you malloc. This is exactly what's happening. You malloc some structure and then you start messing with it and start saying things. Although what do you normally do? What do you use the star operator a lot? What do you use? The arrow. The arrow. So you use something like technically, I think it depends specifically on the compiler. I think you can do it, it's a warning. Because the, whoop, how does this happen twice? Yeah, it's a void star, but there's rules about like you can cast a void star to anything else and it's usually works fine. So it depends specifically. When you set up all warnings, yes, it would give you a warning. Because you wanna be explicit that you're like actually passing it to the thing you want to, right? So what does x, what does this syntax mean? So what does x arrow foo me? The exact same thing. So this is why if you're looking for segmentation faults or null pointer exceptions, which we found are the same thing, right? You need to check not only every instance of dereferencing a program, but also any arrows. Right, so here if x, if on this line x for some reason had the value zero or null, this is gonna throw a null pointer as segmentation fault. Let's go back to the scary one. All right, we have three variables. In x, which is an in pointer pointer, sorry, x, which is an in pointer pointer, y, which is an in pointer, z, which is an int. x, which is malloc, does the size of an in pointer and then cast an in star star, so it's done a little better, y is in star malloc. x is equal to address of y, y is equal to the address of z, y is equal to star x. So, what happens? So this is what you should be able to do, this is a self-check. You should be able to take this and do circle box diagrams at any point in this program's execution, so I could say something like, what's the box circle diagram here? All right, or what's the box circle diagram at the end of the program look like? I'll also usually give you certain things, so I'd say like, this has memory address alpha, this has memory address beta, this has memory address gamma, delta, whatever, so you have something to refer to. I think we're at the end, so. All right, when we come back, we're gonna come back here and go and read some cool examples.