Pointer Arithmetic

One of the strengths of pointers is that you can do basic arithmetic with it. Though arithmetic may originally mean mathematical operators; for pointers, only addition (and subtraction) are defined.

Consider the following code snippet.

You can compile these at Coding Ground.

In memory, it looks similar to the following:

Memory Locations

Variable names are in black (which are replaced by addresses when the code is compiled). Addresses are in decimal and green while Values are in blue. sArr is an array of shorts which are only 2 bytes, which is why the elements are separated only by 2. On the otherhand, fArr is an array of floats which are 4-bytes wide. Hence, elements of fArr are 4-bytes apart.

The memory locations specified above are fictitious. We can’t assign specific memory locations to variables and all those are assumed. I just wanted to point out that array elements are strictly contiguous while other variables cannot be assumed to be beside each other. Only array elements are guaranteed to be side-by-side.

Notice how the value of sp is the address of sArr and fp is of fArr.

Let’s try printing the elements of sArr from sp.

The 2 lines above are perfectly identical since the index operator is converted to addition then dereference.

Now you might start asking: “How can the second element be accessed when sp was only incremented by 1?” Let’s look at printing the elements of fArr by fp.

The code is nearly the same with sp. Again, how can the next element be accessed knowing that it’s 4 bytes away and we only incremented the pointer by 1?

Pointer and Integer Addition

When dealing with addition between pointers and integers, the compiler also considers the data type being pointed to. The integer in the addition does not represent the number of bytes, rather, the number of elements. Given the example above, sp is a pointer to a short. Therefore, sp + 1 is not 1 byte ahead of sp, instead, it’s 1 short ahead of sp. Shorts have a size of 2 bytes, which is why sp + 1 jumps forward by 2 bytes. Similarly, fp + 1 is not 1 byte ahead of fp, instead, it’s 4 bytes ahead because floats have a size of 4-bytes.

pointer arithmetic 2

The integer in the addition need not always be positive. It can be negative which means it’s pointing to an element before.

Be careful not to go out of beyonds! Compilation does not check and may work some times. Dereferencing an invalid location is simply undefined and would byte you back in the future.

Since addition is commutative, the following are legal:

Array Traversal

Let’s see some application to this.

When we wish to traverse an array of elements, we’d normally do this with indices:

Though this may look efficient already, we could further reduce the operations involved. Remember that the index operator is addition then dereference. But we’re already doing some increment with the counter. Why don’t we combine that.

We’ve eliminated that extra addition for a minor benefit. Traversing arrays this way is common practice, especially when you get to Standard Template Libraries (STL) in C++. Just make sure not to dereference it.

Note: I mentioned previously that it is not advisable to point to elements outside the array. But end here seems to defy that rule. The danger is only when you dereference an illegal location.

If you wish to traverse in reverse, you could do the following instead:

Address Difference

Consider the following statements:

The difference between pointer values is the number of elements between them. This assumes that the pointers have the same base type and are pointing to elements of the same array. Otherwise, the result makes no sense.

The difference above could also be evaluated like so:

Keep in mind that the integer values here represent number of elements and not bytes.

Illegal Arithmetic

Technically speaking, addresses are treated as unsigned integers. Hence, negating an address makes no sense. It’s like looking for a negative house number or a negative room number.

Adding two addresses doesn’t make sense either.

Video

Here’s a video lecture that I did a long time ago about pointers and arrays.

Summary

  1. Integers can be added to addresses and are treated as element offsets rather than byte offsets, taking into consideration the data type it’s pointing to.
  2. The difference between two addresses is the number of elements between them, assuming that they’re of the same base type and they both point to elements belonging to the same array.