Skip to content

section7_pointers_arithmetic

Fábio Gaspar edited this page Jan 17, 2019 · 1 revision

Pointers arithmetics

We have seen that pointers are special variables that let's use reference memory addresses. However, pointers also have an extra special property which is related with arithmetic.

Image you have the following memory scenario:

+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
| A | B | C | D | E |   |   |   |
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+----

In this example, you have a set of five variable that are sequentially stored in memory. We will that C supports this kind of storage with arrays, which are covered in the next section.

Let's say that all values are integer values and the only way to access all values is through a pointer variable that contains the address of C.

Also, because each value is a integer, we know each one uses up to 4 bytes. So, we can redraw the picture as follows, where each placeholder is represents the basic memory units: byte.

+--------------------------------------------------------------+
|A0|A1|A2|A3|B0|B1|B2|B3|C0|C1|C2|C3|D0|D1|D2|D3|E0|E1|E2|E3|  |
+--------------------------------------------------------------+
int *ptr; /* points to the C variable, thus it points to C0

If we have the address of C or C0 in the second picture, in order to compute the access to the variable D, or D0, you would compute address(C0) + 4. For instance, if the variable C starts at address 0x100, because it's a integer and uses 4 bytes, then the variable D starts at address 0x104. On the other hand, if the data type was long, which requires 8 bytes, then you would have to compute 0x100 + 8.

Having to worry about what each data type occupies in order to compute addresses makes it difficult to mantain code. With pointers in C, it's much easier. Assuming that the variable ptr is pointing to variable C, if you want to access D then you just do ptr + 1. Want to access A? Well, it's two positions behind, then you just do ptr - 2.

This is extremely useful. When you are working with sequences of data, you don't need to worry about how much space each object requires, you just take the base address of the sequence and add the index of the object you wish to access. This will become more clear with arrays and complex data structures.

int a, *ptr_a = &a;
char b, *ptr_b = &b;
printf("Original address: %p\n", ptr_a);
printf("Example 1: %p\n", ptr_a + 1);
printf("Example 2: %p\n", ptr_a - 10);
printf("Example 3: %p\n", ptr_b + 3);

The output for this program is illustrated below:

Original address (A): 0x7ffce681c834
Original address (B): 0x7ffce681c833
Example 1: 0x7ffce681c838 // 0x7ffce681c834 + 4*1
Example 2: 0x7ffce681c80c // 0x7ffce681c834 - 4*10
Example 3: 0x7ffce681c836 // 0x7ffce681c833 + 3*1