Tip:
Highlight text to annotate it
X
So far in our previous lessons we have seen how to work with pointer variables.
So we pretty much understand the basics, in this lesson we will write some more
code using pointers
and we will look through some of these concepts.
In more detail using some examples, the first thing that I want to point out is
that pointer variables are strongly typed.
What it means is that you need a pointer variable of a particular type
to store the address of the particular type of the variable.
So int* or a pointer to integer will be needed to store the address of an
integer, character pointer will be needed to store the address of a character
and similarly if we have a user defined structure
or class then we need a pointer of that particular
type only but why do we need these strong types.
Isn't it that the pointer variables just store the address of the variable.
So why couldn't we have just one type
that will be some generic type to store the address
of all kind of variables and the answer is that we do not use the pointer variables
only to store memory addresses but we also use them
to dereference these addresses so that we can
access and modify the values in these addresses.
Now as you know datatypes have different sizes
like in a typical modern day compiler an integer
is stored in four bytes, a character variable
is stored in one byte, a float
variable is stored in four bytes and these variables differ not only
in their sizes they also differ in how we store
information in whatever bytes are available for these variables or data
types.
Let's say we have an integer A
and its value is 1025 and this
is how it is led out in the memory.Each bracket here is one bite.
Let's say this particular byte which is the least significant byte
is byte 0 and then we go on like byte
one byte two and byte
three.Now we also know that each byte in the memory
is addressable.Let's say the address of byte zero
is 200 now these four bytes need to be contiguous.Let's say the address of
byte 1 is 201 and then we go on like 202
and 203.When an
integer is represented in the memory, is stored in the memory the
left most bit stores the
information that whether this integer is positive or negative so this is also
called
sign bit and
rest 31 bits are used to store the value. So if you see we have
a one at right most bit with
place value 2 to the power zero and at this particular bit
with place value 2 to the power 10.
So the overall value that we have in binary here
is 1025 in decimal.Now
what if I declare a pointer to integer P
and store the address of A in P by using the ampersand operator.
What will happen if I print the value of P,
the value of P or the address stored in P will be
200 the address of byte 0. So we are kind of saying that we have
the address of an integer variable starting at address 200.
If we dereference this address and try to print
*P we want to know the value at this particular address.
Then the machine sees that ok P is a pointer to
integer so we need to look at four bytes
starting address 200 and then the machine knows that
how to extract the value of an integer datatype.
So
it retrieves the value 1025 out of these
four bytes.Now if P was a character pointer
then while dereferencing the machine would have looked at only one byte
because a character variable
is only one byte.If P was
a pointer to float then although float is also stored in four bytes
but the way information is written for float in these
four bytes is different from the way information is written
for an integer datatype.So the value printed would have been something else.
Let's go write some of this in a real program and see what happens.
In my C program I'll first
declare an integer 'a' equal to 1025
and now i will declare a pointer to integer 'p'
and then i will store the address of 'a' in 'p'
by using the ampersand operator.Now I'll write a print statement
like this size of integer
is and we have a function sizeof in C
which gives us the size of a particular datatype in bytes
and now i will write a print statement like this, address is equal to
'p' and value is equal to
'*p'.We dereference 'p' to print the
value.Now let us see what is the output of this program
no points for guessing this is pretty straight forward the size of integer
is 4 bytes the address that we're showing here is some address
and the value is 1025.
Ok now i will do some trick here I will declare a character pointer let's say the name of
the variable is 'p0'.
Now I will try to put the same address
as we have in 'p' into 'p0' by writing a statement like this
but this will give us a compilation error because 'p0' is a pointer to
character and 'p' is a pointer to integer.
So what we will do here is typecast
'p' to character pointer
and then assign the value and now I will write two more print statements.
First is "size of character is these many bytes" and we use a method sizeof again
and the second is the address is 'p0'
and the value at address is '*p0' so we dereference we try to
dereference 'p0' now
and let us see what's the output now the first line of output is size of integer
is 4 bytes
address, because we are running the program fresh
this address will not be the previous address, the address from the previous run.
This will be a different address by dereferencing the integer pointer
we're getting the value 1025.
Now the next line of output is size of character is one bytes
address is 5373032 which is the same address
as we have in the second line but the value this time
is 1.Now why is this value 1,
once again if we write 1025 in binary using 32 bits
then this will be the representation when we do this
typecasting here trying to store the address of 'p'
in 'p0' then the address of this particular byte
the rightmost byte is stored in 'p0'.
But when we dereference 'p0' because 'p0' is a pointer to character the machines
say that hey this is a pointer to a character
and character is only one byte so I will look at only one byte to see the value
and if you see this particular byte in binary
is 1 and that's why this
output here is one. Ok, I'll write two more print statements now
one to print the address p plus one and the value at address P plus one.
Now as we know we can add or subtract
an integer constant from a pointer variable.
This is allowed in fact the only pointer arithmetic that is allowed is adding or
subtracting some constant integer value to
the pointer. p+1 will take us to the address of the next integer,
so it will skip four bytes and take us four bytes ahead.
Let's say we also want to print p0 plus one and the value at p0 plus
one.
Okay now let's see the output of this particular program
the address of 'a' this time is 4456036
that's what is allocated for 'a' in this particular run.
The value is 1025 p plus one is 445 6040, if you see this is 4 bytes more
than
the address of 'a' because size of integer is 4 bytes and 'p' is a pointer to integer.
So incrementing 'p' takes us
four bytes forward and this value is some garbage value because we have not filled
anything in this particular address so there is some garbage in the memory
which
we are picking up.Now address in 'p0' is also 4456036 which is the address
of the first byte the least significant byte of
'a' the value is 1.
Now p0 plus one is 4456037 here we have
a value which is one byte more and this is because character
is stored in one bytes.Now the value here is four,
if you see p0 plus one will take us to this particular byte
the address of this particular byte and this particular byte in binary
is 4.
This was to show you how things happen in memory when we
dereference a pointer variable by using the Astrick operator
and also what happens when we perform pointer
arithmetic with a particular pointer type.
This typecasting of pointer variable from one to another
also has some use cases.We will discuss them later.
Now we will discuss one pointer type which is generic pointer type.
It does not correspond to a particular datatype and this pointer type is called void
pointer
and we declare this particular pointer type
by using the keyword void and using an astrick sign in front of
the variable name.Again now we can write
something like 'p0' is equal to 'p' we do not need an explicit
typecasting here like this.The statement 'p0' is equal to 'p'
is valid and this will not give you compilation error and because this
particular
pointer type is not mapped to a particular datatype
we cannot dereference this particular pointer variable.So if you try to print
star
'p0' or astrick 'p0' this will give you
an error.We're getting a compilation error.
we can only print the address and as we can see here the address is same as
the address of
'a' and if we perform arithmetic if we try to
do something like p0 plus one access something like p0 plus one
this is also not possible this will also give you compilation error.
We will come back to the use cases of void pointers
in forthcoming lessons.Lets for now know that there is something
called void pointers.So this was diving deep into
pointer types, typecasting and
pointer arithmetic.We will have a lot of fun with pointers in the coming
lessons.
So thanks for watching.