Pointer Arithmetic
What sets C pointer apart from pointers in other programming languages is that in C, we can explicitly operate on it. The operations that can be done are typically just a simple addition/subtraction with numbers. Adding or subtracting two pointers are non-standard but may be allowed. In particular, subtracting two pointers typically finds the difference in subscripts of two array elements (only if allowed in the first place). As we will discuss array in later time, we will ignore this for now.
Incrementing/Decrementing Pointer
First, let us consider incrementing a number.
If we start with a = 2
, performing a++
will increment the value stored in variable a
from 2
to 3
.
That is rather straightforwards.
Now, if we extend this idea to pointer, we have to be careful. If we simply think of the address as an integer, then we may falsely believe that the address will be incremented by one. But remember that different data types have different size.
Type | Size | Usage |
---|---|---|
int |
4 bytes | Whole numbers |
float |
4 bytes | Real numbers |
double |
8 bytes | Real numbers |
char |
1 byte | Characters |
As will be made clearer when we talk about array next time, when we increment a pointer, we do not want to just increment the address by one. Instead, we want to point to the start of the next address of the same type. As such, incrementing an integer pointer will actually increment the address by 4. This is because each address holds one byte of data. So the start of the next address of the same type will be 4 more than the current address.
Similarly, incrementing a double
pointer will add 8 to the address and incrementing a char
pointer will add 1 to the address.
This is summarised in the program below.
IncrementPointers.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
If you look at the actual run, you can ignore the actual value printed. Instead, look at the difference between the two addresses. You may get something like:
1 2 3 |
|
Since the output is in hexadecimal, we have to do hexadecimal subtraction.
But if you simply look a the difference (e.g., between 0x7ffdcea0c548
and 0x7ffdcea0c54c
), you can see that the difference is basically the last hexadecimal digit.
The difference between 8
and c
is exactly 4.
Note that for char
, the difference is only one as shown in the difference between 0x7ffdcea0c543
and 0x7ffdcea0c544
.
Sometime, you have to be careful since the we can easily forgot that we are dealing with hexadecimal.
If you look at the output for double
, it may seem that the difference between 0x7ffdcea0c538
and 0x7ffdcea0c540
is only 2!
But this is wrong because in hexadecimal, that's actually a difference of 8.
Remember, 8+8 = 16 and 16 in hexadecimal is 10.
In this case, we simply increment the number to its left by 1 and set the current number to 0.
BasicPointer.c
Try to trace the following execution on your own before checking the result of the actual run. More importantly, you should practice using box-and-arrow diagram.
BasicPointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
BasicPointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Pointer.c
Try to trace the following execution on your own before checking the result of the actual run. More importantly, you should practice using box-and-arrow diagram.
Pointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Quick Quiz
What is the output if the printf
statement is changed to the following?
printf("%f\n", *b)
printf("%f\n", b)
printf("%f\n", *a)
printf("%p\n", b)
12.340000
- Compile with warning but run with some random value
- Error because
a
is not a pointer - The hexadecimal value of the address of variable
a
Pointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
TracePointer.c
Try to trace the following execution on your own before checking the result of the actual run. More importantly, you should practice using box-and-arrow diagram.
TracePointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
TracePointer.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|