In this video we'll, learn about pointer arithmetic in c++.
In c++, pointers can be used in assignment expressions,
arithmetic expressions and comparison expressions.
C++ allows a subset of the arithmetic operators to
work with pointer variables.
Pointer arithmetic operators only make sense when you use them with
raw arrays, but they're a very powerful way to manipulate them.
Let's start by looking at the increment and decrement operators
in the context of pointers.
The increment operator increments the address stored in a pointer
variable, so that it points to the next element in contiguous memory.
So if integer pointer is currently pointing to address 1000, then integer
pointer plus plus will increment it by the size of whatever it's
pointing to, in this case, an integer.
It's 4 on my machine, so now we will point to 1004.
in the case of a double, it would be larger.
If a pointer is pointing to the address of a very large data
type, then the increment operator would increment it by whatever the
size of that large data type is.
The decrement operator works exactly the same way except
that it decrements the values stored in the pointer variable.
We can also use the addition and subtraction operators with pointers.
The addition operator determines the operand on the right hand side of the
expression and multiplies that number by the size of the element, and that's
what's being added to the pointer.
So adding two to an integer pointer increments the pointer by
two times the size of an integer.
Obviously, pointer arithmetic is machine specific-since the size of c++
types vary from machine to machine.
The subtraction operator works in the same way except that we're
decrementing the pointer's value.
What do you think is the result of subtracting one pointer from another.
Well, if both pointers point to the same data type, then the
result will be the number of elements between the two pointers.
If the pointers point to different data types then
you'll get a compiler error.
Finally, let's see how we can compare pointers.
We can compare pointers with the equality operators.
If we want to compare two pointers, we can simply compare them using
the equal or not equal operators.
But be aware that this will compare the values of the pointer variables.
So if the pointers are pointing to the same address, then they're
considered equal, otherwise they're considered not equal.
The data that they're pointing to is not considered when
checking for equality.
The sample code shows an example of comparing pointers.
In this example, p1 and p2 point to different addresses.
And p1 and p3 point to the same address.
So you can see that if we compare p1 and p2 we get back false.
And if we compare p1 and p3, we get back true.
All three pointers point to strings with the value frank
but that's not considered when you want to compare pointers.
So how do you compare what the pointers are pointing to?
Simple, just follow the pointers, dereference them and then
check what they're pointing to.
I'll show you an example next.
Here we have the same example except that we're dereferencing the
pointers before we're comparing them.
So in this case, p1 and p2 point to different strings but those
strings both happen to be frank, so this will display true.
P1 and p3 point to the same string which is Frank, so
this will also display true.
So that's an intro to pointer arithmetic.
Let's head over to the ide, and I'll show you some more examples.
Okay, so I'm in the IDE, and I'm in the section 12 workspace in
the pointer arithmetic project.
So let's go over a couple of examples of pointer arithmetic.
You can see here that I've got a scores array, which
is an array of integers.
And I've initialized it to 100 95 89 68 and negative 1.
I'm using the negative 1 as a sentinel because what I want to do is I want
to loop through this array and when I see negative one I want to stop.
Okay, so I also have and this is called scores, that's
the name of this array here.
Then I've got my score pointer.
And I'm initializing two scores.
So right now, it's pointing right here.
Let's say that this is addressed a, 1000, 1004, 1008, and we'll
use decimal, here 1012 and 10016, assuming 4 byte integers here.
Okay, perfect.
So now let's loop through this array using the pointer.
Okay, so what I'm doing here is I'm dereferencing score pointer.
So follow the pointer to where it's pointing.
And then I'm checking the value at that location to be negative 1.
Okay, so I want to loop while it's not equal to negative 1.
So I want to loop through this here.
Once I see negative 1 I want to stop.
Okay, so that's what's going to happen here.
So score pointer right now is pointing to memory location of 1000.
I'm going to dereference that I've got my 100.
It's definitely not equal to minus 1.
So what am i going to display, I'm not just playing score pointer
because that would display a 1000, I'm dereferencing score pointer
and that'll display the 100.
Okay, now we get into the pointer arithmetic.
What we're saying is score pointer plus plus, in other words
increment the score pointer.
Well, what do we increment it by.
We're connecting it by whatever it's pointing to.
So in this case, by 4 because I've got 4 byte integers.
So this will no longer point here, it'll now point here.
We go back up to the loop, we check to see if we're pointing to minus
1, we're not, and we display our dereference pointer, which is now 95.
Again, we point to the next one.
Now we're pointing to a 1008, it's not minus 1, so I'm
going to display that 89.
I'm going to increment my pointer again.
Now I'm pointing to address 1012, which is again not equal to minus 1.
I'm going to display the 68, and I'm going to increment my pointer
for the last time right here.
I check to see that my pointer is not pointing to minus 1.
Well, it is.
In this case my dereference pointer.
So I stop.
So this is the way you can loop through an array using a pointer
and a sentinel value in this case.
This is called a sentimental value.
And this is commonly used as the terminator basically.
So you keep looping until you hit a terminator.
Okay, so let me clear this, and let's run this.
And we should see that those array elements display.
And there they are, 100 95 89 and 68.
Those are our four array elements.
We don't display minus 1 because that is our sentinel.
Okay, so that's a simple example of pointer arithmetic.
Now let me show you another way to do this, that's commonly seen.
Okay, so it's everything's exactly the same except you'll notice right
here in the previous example, we had two lines of code, one dereference the
pointer right here and then the other one incremented the pointer to point
to the next integer in the array.
Here we're doing it all in one.
So we've got this piece of code right here.
So we're saying dereference score pointer and increment it.
Okay, so there's a lot going on here and it's important to
understand what's going on.
First of all, we have two operators.
So the first thing we do is we look in the precedence chart to
see which one has precedence.
Well, they both have the same precedence.
So in this case, what we do is we look at the associativity.
The associativity is right to left.
So what that means is that I'm incrementing score pointer.
So I'm incrementing the pointer.
I'm not incrementing the what it's pointing to if
I had something like this.
That's real different now right because what I'm doing here is
I'm dereferencing the pointer, so I'm getting the integer
it's pointing to, and then I'm incrementing that integer, but
that's not what we're doing here.
In this case, what we're doing is we're dereferencing the pointer
and we're incrementing the pointer after we use it. Well, the use is right here.
The use is basically de-reference the pointer and
then increment the pointer.
So it's exactly what we're doing here, right. We are doing
de-reference to pointer and then increment the pointer.
But this, you see a lot in c++ code, right.
You dereference and an increment or a decrement if
you want to go the other way.
If we run this example -- let me clear this real quick, if we run
this example, you'll see that we get exactly the same output 100
95 89 68, exactly the same thing.
Okay, I just wanted to show you that style because you tend to see
this sort of style a lot out there.
Okay, so now let's do another example.
Let me scroll up just a little bit and let's see how we can
compare pointers in this example.
So let's right about here, I'm going to comment this code out or
I should say uncomment this code.
And let's go through this.
So here I've got three string objects: s1 s2 s3.
So they're here s1 s2 and s3.
S1 points to a string, Frank.
S2 also a different string.
Frank.
It's the same Frank but in a different memory location.
And s3 is James.
Now each these objects has a memory location associated with it, right.
So let's say that this one is at a 1000, this one is a
2000, and this one is at 3000.
That way it's really easy to keep them straight.
Perfect.
Now here we go.
Now we've got p1 is a pointer to a string, so it can hold the addresses
of strings that those guys right here are addresses of strings,
so we can assign any of them.
So let's do that.
So what is s1?
S1 is the string object right here, so we can assign the address of s1 to p1.
So p1 now has a 1000 in it, and there's my pointer, right.
P2 is the address of string2, which is 2000.
And there's my pointer to that one.
And now p3, we're assigning the address of s1 again.
So there's the 1000.
And p1 -- p3 goes around this way.
Let me do it that way, it's pointing there.
Okay, so now I'm using the bool alpha modifier, so we
just print true and false.
So let's do some comparisons here.
Does p1 equal p2?
Well, p1 is a 1000.
P2 is 2000.
So no, right.
They both points to strings who are Frank but we're not considering
what this what they're pointing to, we're only considering the
value of p1 and the value of p2, which are definitely different.
So we get back false.
How about this, p1 and p3?
Well, p1 is a 1000 and p3 is a 1000.
So that's definitely true.
Okay, so notice that we're checking the pointer's value
not what it's pointing to.
Now if we want to look to see if we're pointing to the same
string, then what we do is we de-reference the pointers here.
Okay, so you can see here this will output p1, right,
follow p1 so dereference p1.
If I dereference p1, I get Frank.
So this will say Frank compared to dereference p2.
Follow p2, I get Frank again.
Frank is Frank.
That's true because now we're comparing the
strings not the pointers.
Now over here, we've got p1 and p3.
P1 and p3 both point to the same memory address, so obviously what
they're pointing to is the same.
And in this case, Frank is Frank also.
But now let's say we change p3 and we change the pointer in p3 to 0.2 s3.
The address of this guy right here 3000.
So this is now 3000.
We're pointing here.
No longer pointing here.
Now what we're doing is we're comparing -- we're dereferencing
p1, which points to Frank and we're dereferencing p3, which
points to james so now what we're doing is we're comparing
the string Frank and the string James which we get back a false.
Okay, I know it's a lot of pointers to follow, but it's pretty
pretty clear once you really take your time and walk through it.
So let's clear this and give this one a run.
And like I said you can play with this code.
So you can see what's happening here, right.
This address and this address are not true, not the same.
So obviously those pointers are not the same.
In this case, it is the same address, so we have a true.
And then we're comparing Frank and Frank, which is true, Frank
and Frank, which is true and Frank and James which is false.
In the bottom three examples here, we're actually comparing
the strings, not the pointers.
Okay, So let's do one more with subtraction, so you can
see what that looks like.
And I'll uncomment all this out.
And we'll walk through this example.
This is a real simple example here.
In this case what have I got?
I've got name which is an array of characters, right.
So I've got f r a n k and a null character because
this is a c-style string.
So I've got character pointer one.
It's a pointer to a character.
So I can point to any one of these guys here.
And I'm initializing that to null pointer.
And then I've got character pointer two, both nulled out.
Okay, So now what do I do.
I'm saying character pointer one is pointing to the address of
name sub-0, what's name sub 0?
That f, right there.
The address of f.
I could have just said name it means exactly the same
thing, but I wanted to do it a different way so you could see.
So character pointer one is pointing here.
And character pointer two is pointing to remember 0 1 2
3 4 5, in this case, right.
So it's pointing to the address of name sub-3, which is the n.
Right now, assuming that characters are one byte, this would be a 1000.
This one would be at a 1001, 1002 and 1003.
So this would be a 1003 and this would be 1000.
So when I subtract those two pointers like I'm doing right here,
it's subtracting 1003 from a 1000.
And that's what I'm getting back.
There's three characters between those two pointers.
And that's all the point of subtraction means, right.
So let's let's give this a run.
And the last example here says in the string Frank n is
three characters away from f.
And that's exactly what we expected.
Okay, So this gives you a little bit of a intro to pointer arithmetic.
You can see it's pretty straightforward.
Never think of adding 1 or adding 2 or adding 3.
Always think about adding one of the type that I'm pointing to, it
could be 4 bytes, 8 bytes 100 bytes depending on what I'm pointing to.