# 6.8a — Pointer arithmetic and array indexing

Pointer arithmetic

The C++ language allows you to perform integer addition or subtraction operations on pointers. If `ptr` points to an integer, `ptr + 1` is the address of the next integer in memory after ptr. `ptr - 1` is the address of the previous integer before `ptr`.

Note that `ptr + 1` does not return the memory address after `ptr`, but the memory address of the next object of the type that `ptr` points to. If `ptr` points to an integer (assuming 4 bytes), `ptr + 3` means 3 integers (12 bytes) after `ptr`. If `ptr` points to a `char`, which is always 1 byte, `ptr + 3` means 3 chars (3 bytes) after ptr.

When calculating the result of a pointer arithmetic expression, the compiler always multiplies the integer operand by the size of the object being pointed to. This is called scaling.

Consider the following program:

On the author’s machine, this output:

```0012FF7C
0012FF80
0012FF84
0012FF88
```

As you can see, each of these addresses differs by 4 (7C + 4 = 80 in hexadecimal). This is because an integer is 4 bytes on the author’s machine.

The same program using `short` instead of `int`:

On the author’s machine, this output:

```0012FF7C
0012FF7E
0012FF80
0012FF82
```

Because a short is 2 bytes, each address differs by 2.

Arrays are laid out sequentially in memory

By using the address-of operator (&), we can determine that arrays are laid out sequentially in memory. That is, elements 0, 1, 2, … are all adjacent to each other, in order.

On the author’s machine, this printed:

```Element 0 is at address: 0041FE9C
Element 1 is at address: 0041FEA0
Element 2 is at address: 0041FEA4
Element 3 is at address: 0041FEA8
```

Note that each of these memory addresses is 4 bytes apart, which is the size of an integer on the author’s machine.

Pointer arithmetic, arrays, and the magic behind indexing

In the section above, you learned that arrays are laid out in memory sequentially.

In lesson 6.8 -- Pointers and arrays, you learned that a fixed array can decay into a pointer that points to the first element (element 0) of the array.

Also in a section above, you learned that adding 1 to a pointer returns the memory address of the next object of that type in memory.

Therefore, we might conclude that adding 1 to an array should point to the second element (element 1) of the array. We can verify experimentally that this is true:

Note that when performing indirection through the result of pointer arithmetic, parenthesis are necessary to ensure the operator precedence is correct, since operator * has higher precedence than operator +.

On the author’s machine, this printed:

```0017FB80
0017FB80
7
7
```

It turns out that when the compiler sees the subscript operator ([]), it actually translates that into a pointer addition and indirection! Generalizing, `array[n]` is the same as `*(array + n)`, where n is an integer. The subscript operator [] is there both to look nice and for ease of use (so you don’t have to remember the parenthesis).

Using a pointer to iterate through an array

We can use a pointer and pointer arithmetic to loop through an array. Although not commonly done this way (using subscripts is generally easier to read and less error prone), the following example goes to show it is possible:

How does it work? This program uses a pointer to step through each of the elements in an array. Remember that arrays decay to pointers to the first element of the array. So by assigning `ptr` to name, `ptr` will also point to the first element of the array. Indirection through `ptr` is performed for each element when we call `isVowel(*ptr)`, and if the element is a vowel, `numVowels` is incremented. Then the for loop uses the ++ operator to advance the pointer to the next character in the array. The for loop terminates when all characters have been examined.

The above program produces the result:

```Mollie has 3 vowels
```

Because counting elements is common, the algorithms library offers `std::count_if`, which counts elements that fulfill a condition. We can replace the `for`-loop with a call to `std::count_if`.

`std::begin` returns an iterator (pointer) to the first element, while `std::end` returns an iterator to the element that would be one after the last. The iterator returned by `std::end` is only used as a marker, accessing it causes undefined behavior, because it doesn’t point to a real element.

`std::begin` and `std::end` only work on arrays with a known size. If the array decayed to a pointer, we can calculate begin and end manually.

Note that we’re calculating `name + nameLength`, not `name + nameLength - 1`, because we don’t want the last element, but the pseudo-element one past the last.

Calculating begin and end of an array like this works for all algorithms that need a begin and end argument.

Quiz time

Question #1

Why does the following code work?

Show Solution

Question #2

Write a function named `find` that takes a pointer to the beginning and a pointer to the end (1 element past the last) of an array, as well as a value. The function should search for the given value and return a pointer to the first element with that value, or the end pointer if no element was found. The following program should run:

Tip

`std::begin` and `std::end` return an `int*`. The call to `find` is equivalent to

Show Solution

 6.8b -- C-style string symbolic constants Index 6.8 -- Pointers and arrays

### 248 comments to 6.8a — Pointer arithmetic and array indexing

• Bryan

This is my answer for question #2; is it ok to directly use the pointer to the beginning of the array that was passed in as an argument? I see that the official solution didn't do that. Also, is it ok to use operator< instead of "!="?

• yeokaiwei

1. Feedback. Quiz 2 was hard to start. This was my initial thoughts. It's junk. The main difficulty lay in what do I initialize the paramaters as, *ptr or ptr.

• Uyph

Hi. I'm sorry if the code looks messy, I'm still working on it but there's an error on line

that prevents me from advancing further. It says 'cannot convert char** to char* in intialization'.

Can you help me check?

• nascardriver

`theString` is a `char[]`, which is the same as a `char*`. The `&` operator returns a pointer to the variable. The variable is a `char*`, so a pointer to a `char*` is a `char**`.

• Naïm Gómez Cano

How can I get the value of a 2D array using  adding and indirection, for example: int arr[3][2] = {{7,2}, {3,4}, {5,6}};
I have tried things like *(arr + 3) to get the value of position arr[1][0] but it doesn't work. It returns me a memory address.
Sorry for the spelling, I don't speak English. Thanks!

• nascardriver

`*(arr + 3)` would return the subarray at index 3 (Which doesn't exist). Let's stick with `arr[1][0]`, because that's a valid element.
First you need to find the subarray at index 1, that's `*(arr + 1)`.
Then you get get element 0 from this subarray using another indirection `*(*(arr + 1) + 0)`.

• Glenn

Just a brief observation: you've begun to use the term 'dereference' in this lesson, but in a way that suggests we should know what it means. I don't *think* you've defined it for us previously, so something of an intro to the implications of the term might be useful here. Thanks!

• nascardriver

"Dereference" was briefly mentioned in lesson 6.7, it's a synonym for "indirection through". I must have forgotten to update this lesson, thanks for pointing out the inconsistency!

this program with ptr++ points to next memory address not next integer

and this show me:
0 : 0000001267EFF800
1 : 0000001267EFF804
2 : 0000001267EFF808
3 : 0000001267EFF80C
4 : 0000001267EFF810
5 : 0000001267EFF814
6 : 0000001267EFF818
7 : 0000001267EFF81C
8 : 0000001267EFF820
9 : 0000001267EFF824

These blocks are in a row but you said ptr++ points to next integer

• nascardriver

0000001267EFF800
0000001267EFF801
but the next integer is at address
0000001267EFF804

• Alessandro Lodi

On my machine, if I run this code

I get the following output:

the memory add of the first element is: 00F6FD98
the memory add of the second element is: 00F6FD9C
the memory add of the third element is: 00F6FDA0
5 at the memory address: 00F6FD8C

Why the two memory addresses for the second element are different?

• nascardriver

is the address of the `found` variable, not of the array element.

`found` is a pointer to the found element. `&found` is a pointer to the pointer to the found element.