In part 1, we learned the basics of pointers. In part 2, we learned what it meant to pass a variable by value or reference. Remember in part 2 I said that when C passes an array to a function, it passes the pointer to the first element of the array and then pointer arithmetic takes care of the rest? Let's find out what I mean.
What is Pointer Arithmetic
Simply put, pointer arithmetic is the math you do to find out where the next item in an array might be based on the data types of that array.
How it works
Every variable takes up some amount of memory in the computer. For example, integers are often allocated 4 bytes. Some compilers allocate 2 bytes, but in the examples before, my integers were 4 so lets go with that. Basically, with 4 addresses, an integer has this much to work with:
0000 0000 0000 0000 0000 0000 0000 0000
If all those bits were turned on, the number would be 2,147,483,647, and hence is the biggest number a 32 bit (4 byte) integer can be.
So, if we have an array of 3 integers, we know the array will take up 12 bytes. We also know that if the first value in the array is at address 0x7ffc763f2444, then the second value will be at 0x7ffc763f2448, and the last value will start at 0x7ffc763f244c (because this is hexadecimal).
Let's go ahead and dive into some code explaining this:
#include <stdio.h>
int main() {
int array[3] = {10, 20, 30};
printf("Address of first element (the number 10): %p\n", &array[0]);
// If we add 1 to the pointer, it should
// show us the value of array[1], the
// number 20
int *first_addr_in_array = &array[0];
int *second_addr_in_array = first_addr_in_array + 1;
printf("Second array value is: %i\n", *second_addr_in_array);
printf("Subtracting the second and first array addresses: \n");
printf("%ld\n", second_addr_in_array - first_addr_in_array);
// Finally, the address of the third
// element in the array, array[2],
// minus the address of array[1] will
// be 1. Also, the value will be 30
int *third_addr_in_array = &array[2];
int difference_between_2nd_and_3rd = third_addr_in_array - second_addr_in_array;
printf("The difference between 2nd and 3rd array addresses: \n");
printf("%i\n", difference_between_2nd_and_3rd);
printf("The address of the 3rd element in the array: ");
printf("%p\n", third_addr_in_array);
printf("The value of the 3rd element in the array: ");
printf("%i\n", *third_addr_in_array);
return 0;
}
Compile and run, here's what I get:
Address of first element (the number 10): 0x7ffdd20386c
Second array value is: 20
Subtracting the second and first array addresses:
1
The difference between 2nd and 3rd array addresses:
1
The address of the 3rd element in the array: 0x7ffdd2038d74
Please excuse my modulation between 1st and first
So what the heck did we do here?
Well, first we created an array with the values 10, 20, and 30. Then, we got the address of the first element in the array. This is the value a function would get if you were passing it this array as an argument.
Then, we added 1 to the address and looked at what value would be there. As we expected, we got 20. C is smart enough to know that this is an integer array and that we add one, we're really adding the size of the data type to the address to get to the next value. For integer arrays, the values are 4 addresses apart. If this were an array of short
s, the elements would be 2 addresses apart.
Then, just for fun, we subtract some memory addresses to see if we still get what we think we will (we do).
This is the basic idea behind pointer arithmetic, it's really not that hard.
Series Wrap Up
I really hope this series was short enough to hold your attention, and informative enough to help you understand this fundamental concept a little bit better. You may go your whole programming life without ever having to think of pointers, but they will always be there. It doesn't hurt knowing a little more about them. If you have any questions, please feel free to comment here or @ me on Twitter.