Save up to 80 % on our C and C++ e-learning courses. Only this week!

# Lesson 3 - Pointer arithmetic in the C language

In the previous lesson, Dynamic memory allocation in the C language, we learned dynamic memory allocation. In today's C tutorial we're going to work with pointers even more. We'll learn to perform basic arithmetic operations with them, work with them using indexes and we're going to create a simple program to calculate the grades average.

## Pointer arithmetics

Since pointers are actually memory addresses, you might have wondered if we can calculate with them in some way. This is exactly what pointer arithmetic is about.

We have the application from the last lesson that creates a memory block for 100 `int`s. We know that the pointer `p_i` points to the first `int` of this block (or a dynamic array, if you want). But how do we get e.g. to the 5th `int`?

We know that the individual `int`s lie immediately next to each other in the memory. Therefore, we can calculate the address of the fifth element by taking the address of the pointer `p_i` (the 1st element) and adding four times the size of `int` to it. This gives us the address of the 5th element and we'll store it as a `p_fifth` pointer.

The C language makes the whole thing easier for us allowing us to add/subtract integers to pointers. For example, once we add one to a pointer, C will not increase its address by 1, but by the size of the element type the pointer points to. Therefore, in arrays, we move forwards or backwards (if we subtract) by n elements.

The code for working with the fifth element of our dynamic 100-int array would look like this:

```int *p_i, *p_fifth;
// Allocation of 100 times the size of int
p_i = (int *) malloc(sizeof(int) * 100);
if (p_i == NULL)
{
printf("Not enough memory.\n");
exit(1);
}

// Calculate the address of the fifth element
p_fifth = p_i + 4;

// Set the value of the fifth element
*p_fifth = 56;

// Freeing the memory
free(p_i);
p_i = NULL;```

Although it may have seem so, pointers are not just numbers with addresses, C works with them in a different way. `+ 4` actually caused the number `16` to be added to the address (because `4` ints occupy `16` bytes).

### Subtracting pointers

If we have 2 pointers pointing to the same memory block, we can subtract their values. If each pointer pointed to data not related to the each other, we'd get nonsense. However, if one pointer would point e.g. to the beginning of a dynamic array of `int`s similar to the one we created the last time, and the other would point to the fifth element of this array, we'd get number 4 when subtracting the pointers. Let's test this by adding the following line somewhere before freeing the memory in the program above:

/ --- code cpp printf("The element p_fifth is pointing to has the index %d in the array.", p_fifth - p_i); \ ---

The result:

```c_pointer_arithmetic
The element p_fifth is pointing to has the index 4 in the array.```

Notice that we subtract the first element from the fifth. This is because the fifth one is further in the memory.

### Comparing pointers

If 2 pointers point to the same memory block, but maybe elsewhere in it, we can compare them using the standard operators `<`, `>`, `==`, `<=`, `>=`, and `!=`. Like this we can find out whether the first pointer points to the element before the element to which the second pointer points, whether they point to the same element or the first one points to the element which is further in the memory.

```if (p_fifth > p_i)
{
printf("In the memory, p_fifth is after p_i");
}```

The result:

```c_pointer_arithmetic
In the memory, p_fifth is after p_i```

## Pointers and arrays

We can work with the 100-int memory block we declared above using pointer arithmetic. It shouldn't be a problem for us to fill the array with numbers, e.g. with zeros (Although we got some memory from `malloc()`, we can never be sure what is stored in it).

The code filling the array with zeros would look something like this:

```int *p_position;
for (p_position = p_i; p_position < p_i + 100; p_position++)
{
*p_position = 0;
}```

We create an auxiliary pointer and move it one element forward in a loop until we reach the end of the block. Using this pointer, we travel through the whole block and set zeros to its elements.

However, we can work with memory blocks just like with arrays since the C arrays are nothing but blocks of contiguous memory. In the same way, we can set all the `int`s to `0` using the following approach:

```int i;
for (i = 0; i < 100; i++)
{
p_i[i] = 0;
}```

We can access the elements in the block as if it was an array, using brackets and indexes. The first approach using pointer arithmetic is faster, since C just adds bytes to the address. When using indexes, C has to multiply the `int` size by the index and add that number to the address of the beginning of the array, which takes a little more time. The differences are usually negligible for normal work, but since we are programming in C, we'll try to do it effectively.

## sizeof()

If you wonder what the following code returns:

`sizeof(*p_i);`

It's the size of a single element of the block `p_i` points to. In our case, 4 bytes (the `int` size). Unfortunately, we can never determine the number of elements of a memory block (in our case, 100) and we need to remember it or store it somewhere when creating the block. This is why we make strings end with the `'\0'` character.

Perhaps we might be interested in what the `sizeof(p_i)` operation would do (notice the missing asterisk). In this case, we'd get the size of the pointer itself, not the size of what it points to. The pointer size will be the same for all pointer types, i.e. `sizeof(char*)` is equal to `sizeof(int*)`. This is because pointers only point to places in memory in principle. To store a memory address, we always need the same data type. For example, for the 32-bit architecture, the pointer size will be 4 bytes, for the 64-bit architecture 8 bytes.

## Example: Calculating the average of numbers

Because we have been theorizing for a quite long time, let's finally show a real example of what we have learned. The program below asks the user how many grades they want to enter. Then, it creates an array for them in the memory, and stores the grades in it, one by one. At the end, it prints the average of these marks.

You might object that we could calculate the average even without storing the grades. However, if we were interested in, for example, the median, or we wanted to work further with the grades, which happens basically all the time in programs, we'd need the data to be stored somewhere.

```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
int count, *p_i, *p_position;
printf("Enter the number of grades: ");
scanf("%d", &count);
// Allocate a block of the given number of ints
p_i = (int *) malloc(sizeof(int) * count);
if (p_i == NULL)
{
printf("Not enough memory.\n");
exit(1);
}
for (p_position = p_i; p_position < p_i + count; p_position++)
{
scanf("%d", p_position);
}
int sum = 0;
for (p_position = p_i; p_position < p_i + count; p_position++)
{
sum += *p_position;
}
double average = (double)sum / count;
// Freeing the memory
free(p_i);
p_i = NULL;
return (EXIT_SUCCESS);
}```

The result:

```c_average
Enter the number of grades: 5

The source code should be understandable as it's similar to the examples above. Note that when storing grades to `p_position` using `scanf()`, we don't use the `&` or `*` characters because the pointer is an address itself which `scanf()` expects as a parameter. Another point of interest is casting one variable to the `double` type when calculating the average. If we divide 2 whole numbers in C, the result is always integer. If we want to divide with a decimal result, at least one of the numbers must be decimal.

The program is free for download in the attachment including the source code.

Okay, after today's lesson, we can create arrays of any size at runtime. However, we still need to specify its size. So how can we create a list of goods of a warehouse that is not limited at all and to which we can add items indefinitely? This is what you will learn later in the next lesson, Dynamic strings and structures in the C language.

Application includes source codes in language c

Article has been written for you by David Capka