Now that you know how a pointer can be used to separate groups of items, I’m going to explain another use of pointers that helps you work with the individual items in the group through a special concept called pointer arithmetic.

You can add or subtract values from your pointer and it will advance or move backwards the appropriate amount based on how many bytes the item type requires. Most computer languages define an int to occupy 4 bytes of memory. If you have an int pointer and its value is 100, that means there should be an integer at the 4 bytes of memory with addresses 100, 101, 102, and 103. You need all 4 of these bytes to make up that single integer. If you now add 1 to your int pointer, its value doesn’t go from 100 to 101, but it goes from 100 to 104. That’s because the next integer must begin at the next memory address which is 104. With an int pointer, you’re counting by fours. This pattern repeats in both directions. That means if you have an int pointer that’s currently pointing to address 100 and you add 3, then it will change to point to address 112. And if you have an int pointer currently pointing to address 100 and you subtract 5, then it will change to point to address 80.

This table shows how a couple integers could be found in memory. The table shows two columns but that’s just for labelling purposes. Computer memory does’t really have columns. It’s just a series of values where each value has an address. So think of the column labelled “Memory Value” as containing the actual values stored in memory while the other column is there just so you can see what the address of each value would be.

Memory Address Memory Value
99 Some byte value
100 Part of int #1
101 Part of int #1
102 Part of int #1
103 Part of int #1
104 Part of int #2
105 Part of int #2
106 Part of int #2
107 Part of int #2
108 Some other byte value

Listen to the full episode or read the full transcript below for more about pointer arithmetic.

Transcript

Don’t worry, in case you haven’t figured it out by now, I’ll let you in on a secret. Programmers don’t need a lot of math. Sure, you need a lot of math to get a computer science degree from a university but that’s just because science degrees in general need a lot of math. If you mastered the ability to count by twos, or by threes, or by some other number in grade school, then you’ll have no problem with pointer arithmetic. If you do happen to be good at math, then don’t get me wrong, there are lots of programming jobs that will be able to make use of that. I’m talking about math as it relates to the majority of programmers.

Okay, back to pointers. Let’s say that you get an order for 10 super widgets but each one needs to be sent to a different mailing address. You use your index card with its pointer to find out on which shelf the super widgets currently reside and bring back 10 of them. Then you line the super widget boxes up one after the other in your address labeling machine. Your company just invested a lot of money in the latest labeling machine and the salesperson couldn’t stop talking about how this new model just needs you to point to the first box and it does the rest. Well, the salesperson simplified things a bit because when you first tried using the new machine last week, it printed all the labels on the first box and kept going until it jammed. It took you a whole day to clean out the sticky mess. The salesperson was right about pointing to the first box, but you discovered that you need to provide two more pieces of information before you finally got the hang of this.

It seems obvious now that that the first piece of missing information is how many boxes to label. I mean a pointer to the first box isn’t enough to know if there’s 1, 2, or 12 boxes total.

But a pointer to just the first box is enough to get things going. Whenever you have a collection of items you can work with the collection as a whole by using just a pointer to the first item.

The second piece of information that really makes it all click together is how big each box is. That’s important because when the machine sticks the mailing address on the first box, it needs to know how far to advance the line of boxes so that the next box is positioned correctly to receive its label. Bigger boxes means bigger advancements. Once you know how far to advance to get to the next box, that pointer to just the first box becomes your key to accessing the other boxes.

Computer programming pointers work a lot like this labeling machine. You start out with a bunch of items in memory and place them one after the next. You also start out with a pointer that identifies where in memory the first item exists. Now the next memory address might still belong to the same item if each item is big enough to require many bytes of memory. When you want to advance to the next item, it would be tedious indeed if you had to sometimes add 3, sometimes add 43, or for other item types add 143. You can’t change how the items will be laid out in memory. If an item takes 143 bytes of memory, then it’s gonna need 143 bytes. But you shouldn’t need to know this. That’s the job of your compiler. You compiler can figure out how big something is and keep track of those details. All you really want is to move your pointer to the next item. So when you add one to a pointer, just be aware that the actual address that the pointer points to might change by a lot more than just 1. It all depends on what type of thing the pointer points to. Just like the labeling machine depended on the size of each box.

You can add or subtract values from your pointer and it will advance or move backwards the appropriate amount based on how many bytes the item type requires. Most computer languages define an int to occupy 4 bytes of memory. If you have an int pointer and its value is 100, that means there should be an integer at the 4 bytes of memory with addresses 100, 101, 102, and 103. You need all 4 of these bytes to make up that single integer. If you now add 1 to your int pointer, its value doesn’t go from 100 to 101, but it goes from 100 to 104. That’s because the next integer must begin at the next memory address which is 104. With an int pointer, you’re counting by fours. This pattern repeats in both directions. That means if you have an int pointer that’s currently pointing to address 100 and you add 3, then it will change to point to address 112. And if you have an int pointer currently pointing to address 100 and you subtract 5, then it will change to point to address 80.

But what about void pointers? These are pointers that still point to a memory address, you just don’t know anything about that memory. It could be an int that takes up 4 bytes or it could be some custom type that takes up several hundred bytes. Before you can use that memory, you have to tell the compiler what assumptions you’re making. In other words, it’s like you have knowledge of what’s going on that’s beyond your compiler’s understanding. Remember the compiler can help you if you let it. It’s really good at keeping track of types. But you do have the ability to hide the types from the compiler and keep track of them yourself. All I can say is that you’re asking for trouble.

Pointer arithmetic also breaks down with void pointers. When you add 1 to a void pointer, the compiler no longer knows what type the pointer points to so cannot advance the pointer to the next instance of that type. There is no type. All it can do is literally add 1 to the memory address. So if you have a void pointer with the value of 100 and you add 1 to it as in the last example, it does change to 101 this time.