# 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 dereferencing 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 dereference! 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. Each element is dereferenced by the switch expression, 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
```

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

• p1

I have a question,when we use a cstring array of chars such as:
char name[] = "Mollie"
and we print it out;
std::cout << name;
It prints out the string,but when we use a different array such as:

int number[]{1,2,3};
std::cout << number;

It prints out the adress of the first element(0 element).
Why is that?

• `name` decays to a pointer. `std::cout <<` treats `char*` as strings.

• Benur21

Why doesn't it treat them as pointers like normal?

• Because then you wouldn't be able to print C-style strings

• Ninnie

Hi Alex!
For the "Using a pointer to iterate through an array" section, why did you write

in Line 7?

• Alex didn't update all lessons yet. It should be

See lesson 1.4 for information about brace initialization.

• Eberhart Petersen

There is one part confusing me in the loop:

We create a pointer of type char and assign it to the array name. So ptr shows to the first element of the array name. I do not understand how the terminating condition

in the for loop works. I assume the address of ptr is compared to the address of name + arrayLength. If i try to print name + arrayLength using std::cout I do not get any output. Why does the compiler know to compare ptr to the address of name + arrayLength?

• name + 0 points to the first character
name + 1 pointer to the second character
...
name + arrayLength points to the 0-terminator

If you print a pointer to a 0-terminator, you're not getting any output, because there is no text.

• Eberhart Petersen

Thanks for the quick answer which helped me understand much more. Since this was my first question i want to say that this is by far the best tutorial i have found so far. I highly prefer reading through this tutorial than watching tutorial videos.

One more question concerning this topic. If we use name (an array which decays to a pointer under certain conditions) in some kind of arithmetic calculation, will the address of the first element be used instead of the assigned character sequence "Mollie"? Because if i try to print name in the loop it will still print

• `std::cout` treats `char*` as a string. It doesn't matter if it points to the beginning of a string, somewhere into a string, or to anywhere else.

• Vasco Esteves

Ahhh, finally array+length makes sense!!!

Back on lesson 6.4 this comes up:

Maybe it would be worth mentioning the usage of std::sort will be explained later in the chapter due to how the compiler interprets arrays...

Anyway, this is my first post here so I'll take the chance to thank Alex and the rest of the gang for this great site. Just so you know, I'm not using AdBlock ;)

• Entertainment channel

why does ++*ptr; changes the char u to V?
in a char array called block[]={'B','U','K','U','T','\0'};

• @ptr is pointing to a 'U'.
*ptr returns a reference to that 'U'
++*ptr increases 'U' by 1, making it a 'V'

• In

How do you ++ a char??
And why are you adding name and arrayLength together??? This is so confussssinnggg.

• A `char` is an integer. See lesson 4.11.
`name + arrayLength` gives you the first character after the name is over, ie. a pointer to the 0-terminator.

• Gianne Flores

Hello!
Is it possible to change an index in array using pointers instead of doing arr[4] = 5;
Thank you!

• You can never change an index. If you're talking about accessing an element, you can do so via pointers.

• Dimitri

Hi, dear teachers!

As I can see char array pointers works different than ints

Is there a way to print the address of the third element for example?

prints "llie"

I guess we can find out address of the first element

and then calculate adress of any element using scaling, but is there any direct way to do this?

Thanks and sorry for my english

• is a char**, ie. a pointer to the pointer to the first element of the array.

is a pointer to the third element.
@std::cout::operator<< treats char pointers as strings. If you want to print it as an address, you need to cast it.

• Max Morgan

Hello!

After we declared the *ptr = name in the for loop, I noticed that we stopped using *ptr and just used ptr. However, we went back to using *ptr when writing the switch statement.

Can you tell me why this is?

Thanks!!

• The asterisk is part of the type

@ptr is a char pointer.

The address stored in @ptr is compared. Not the value @ptr is pointing to.

This asterisk indirects @ptr (It reads the value @ptr is pointing to).

• Max Morgan

Thanks! That makes a lot of sense!

The asterisk was first used to declare the ptr, then we did not use the asterisk in the for loop after because we wanted to look at the memory addresses of the elements in array name. Then we dereferenced the ptr in the switch statement because we wanted to look at the elements (to see if there were vowels) as opposed to looking at the memory address.

Thanks a bunch Nascar!

• Exactly! I'm glad I could help.

• hassan magaji

Hi Alex, Nas..., ...others,
I have a question,
between pointer arithmetic and array indexing which one is faster and which one will you recommend?

nice resource by the way.

• There's no difference

• Alex

For accessing the elements of arrays, favor array indexing. It's a cleaner syntax, and expresses your intent better.
Use pointer arithmetic when moving a pointer (typically through an array).

• Helliarc

So don't do this?????

haha!

• James III

Hello - can anyone please tell me why I can't seem to get a pointer to point to an array? I am using Visual Studio 2017 Community. Here is the code I wrote:

If I initialize "int *numberPointer = numberArray;" at line 18 and comment out the original initialize to nullptr above, I get this output:

The array output from 0 to 99 is printed here.
numberPointer = 0
numberPointer plus 1 = 00F6FA74
numberTotal = -858988510
Hello World!

If I put an "*" in front of numberPointer++, at "numberPointer plus 1 = ", the numberPointer plus 1 output becomes 0. Thank you very much!

• Hi James!

* Line 10, 11, 14, 15, 27: Initialize your variables with uniform initialization. You used copy initialization.
* Line 12: Initialize your variables with uniform initialization.
* Line 1, 10, 18, 19, 20, 21, 22, 27, 28, 29: Limit your lines to 80 characters in length for better readability on small displays.
* Use ++prefix unless you need postfix++
* Line 33: No need for brackets
* (!) Line 18: You're dereferencing a null pointer. You want

* Line 26, 27: You're trying to access index 100, which doesn't exist
* Inconsistent use of @std::endl and '\n'

• James III

Hello nascardriver, and thank you for getting back to me! I did some adjustments
to my code to your recommendations and the code works fine now and gives me the
result of 5050. I didn't use uniform initialization for numberArray so I
wouldn't have to type out {0, 1, 2, ... , 98, 99}. I hope this is acceptable for
initializing large arrays?

Sorry for exceeding the 80 character length for some of those lines. I was just
line length.

The "Hello World!" came with the creation of the project in Visual Studio and
I just didn't bother to change the \n to std::endl.

Here is the working code:

Again thank you and thank you for publishing this c++ tutorial, which
I believe is the most comprehensive free tutorial out there. A lot is
coming back to me after taking a C course in college 20 years ago when
Borland Turbo C and #include "conio.h" (it made for some colorful
output) were popular.

• i used turbo c++ 2 years back and played a lot with colors and delays but now i realised that my fundamentals are not much strong that's why i'm here.

• > thank you and thank you for publishing this c++ tutorial
I am not associated with learncpp, I just reply to comments. @Alex (Cat avatar, blue comment background) is the sole author and maintainer of learncpp.

> which is the best way [to sum up an array]
@std::accumulate

> which is the best way [to access array elements]
Most of the time, by their index.

> gives me the result of 5050
That's wrong though. The sum of 0 + ... + 99 is 4950. 5050 is the sum of 1 + ... + 100, but that's not what you're calculating. You're only getting 5050 because of a programming mistake.

• James III

Thank you nascardriver for getting back to me again. I'm going to take some
time to digest all this. And thank you Alex for publishing learncpp - a
superb tutorial!

btw - I've been going over and over this code, and I cannot figure out how
numberArray[0] got the value of 100 in the loop:

• *numberPointer == *(numberPointer + 0) == numberPointer[0]

Increment and decrement operators are covered in lesson 3.3

• Megan

FYI, there is an error in the last example (Using a pointer to iterate through an array) -- you forgot to include "std::" for "cout".

• Gonor

[

#include <algorithm> // for std::swap, use <utility> instead if C++11
#include <iostream>
#include <typeinfo>
#include <iostream>
#include <array>
using namespace std;
void printLength(const std::array<double, 5> myArray)
{
std::cout << "length: " << myArray.size();
}
void something(int array[6])
{
cout<<"In something function\n";
cout<<sizeof(array)<<"\n";
return;
}
int main()
{
char name[7] = "Holley";
cout<<name[0]<<"\n"<<name[1]<<"\n"<<name[2]<<"\n"<<name[3]<<"\n"<<name[4]<<"\n"<<name[5]<<"\n";
cout<<&name[0]<<"\n"<<&name[1]<<"\n"<<&name[2]<<"\n"<<&name[3]<<"\n"<<&name[4]<<"\n"<<&name[5]<<"\n";
cout<<name<<"\n"<<name+1<<"\n"<<name+2<<"\n"<<name+3<<"\n"<<name+4<<"\n"<<name+5<<"\n";
cout<<&name<<"\n";

int array[6] = {2, 3, 4, 5, 6, 7};
cout<<array[0]<<"  "<<array[1]<<"  "<<array[2]<<"  "<<array[3]<<"  "<<array[4]<<"  "<<"\n";
cout<<array<<"  "<<array+1<<"  "<<array+2<<"  "<<array+3<<"  "<<array+4<<"  "<<"\n";
cout<<&array[0]<<"  "<<&array[1]<<"  "<<&array[2]<<"  "<<&array[3]<<"  "<<&array[4]<<"  "<<"\n";
something(array);
cout<<"array size "<<sizeof(array)/sizeof(array[0])<<"\n";

double score[] = {10.2,34.5,67.5,67.8,89.5,34.5,91.5};
double maxscore = 0.0;
for(auto &value : score)
if(value>maxscore) maxscore = value;
cout<<maxscore<<"\n";

double *iptr = score;
cout<<"address of pointer "<<&iptr<< " and the value tath the pointer points to "<<*iptr<<"\n";

cout<<"enter a name \n";
string name1;
getline(cin, name1);
int counter=0;
string names[] = {"Luke","Kenny","Pilt","Gonor"};
for(auto &values : names)
if(name1==values)
counter++;

if(counter==0)
cout<<"The name is not in the list \n";
else
cout<<"The name is in the list \n";

std::array<double, 5> myArray { 9.0, 7.2, 5.4, 3.6, 1.8 };

printLength(myArray);

return 0;

}
]

• Marcos O.

Long live Alex and NascarDriver!!

• Piyush

int name[]={1,2,3};
int *ptr=&name;

Why this code gives the following error:-
Cannot convert 'int(*)[3]' to 'int*' in initialization.

• @name can decay into a pointer. &name is an int(*)[3], which decays into int**. So you're trying to store an int** in an int*.

• Alexandra

Hello, my name is Alexandra and I am confused about how the switch (*ptr) accessed each member of the char array? Also, why do you use ++ptr instead of ptr++?

Thank you.

-Alexandra

• Hi Alexandra!

The switch is inside a for-loop. On the first iteration of the loop the first character of @name is checked. Then ++ptr is executed, @ptr now points to the next character. Repeat that until the string ends.

Assuming no compiler optimization, ++prefix is faster than postfix++, because postfix++ needs to store the previous value of the variable.

Pseudocode

• Max Ludero

Hello. Thank you again for these tutorials! I need some help understanding. I was expecting to see a sequence of memory addresses.

But instead I got this result:
Fido
ido
do
o

• Hi Max!

@std::cout::operator<< treats char* as text. If you want to print the address, you need to cast to void* or @std::uintptr_t.

• GHG

I have a question?
In the following code:

Can we access this way other random variables from this or other programs, or leads it to undefined behavior

• > from this
Yes

> from other programs
No

> undefined behavior
Yes

• Hi Nguyen!

Arrays can decay into pointers without loosing information other than their size, so yes, your assumption is correct.

* Use uniform initialization
* Use the formatting feature of your editor

• Nguyen

Hi

I modified the program to see if ptr[0] = array[0], ptr[1] = array[1]....prt[11] = array[11].  The output is what I expected.  Please let me know if my assumption is correct.

Thanks, have a great day.

• Hi

Using the above example (Mollie)as the basis, it is easy to translate into a program that will take any name and sort the number of vowels using the pointer system:

Secondly, if I create a 3 dimensional array how do I get it to output to the screen in a graphical format (cube)?

• Alex

> Secondly, if I create a 3 dimensional array how do I get it to output to the screen in a graphical format (cube)?

You'd have to create a graphical application and then render it somehow. That's way outside the scope of these tutorials.

• Piyush

I think it can be done using characters placed at different location in the screen using some  loops and character formatting.

• Infinite

In the last example, was  Ian example of when to use c style strings instead of regular strings?

• Abraham

What means the expresion

exactly?
When we declare not a poiter we had something like

here?

• nascardriver

Hi Abraham!

@ptr is a number. Example: Let's say @ptr is 0xA7E0. That's the address of the name. Here's what the memory from that address onward looks like:

We only want to loop to the end of the string. So we need to keep looping as long as (ptr < 0xA7E7). 0xA7E7 is (0xA7E0 + 0x07) which is (name + arrayLength).

The loop could be reduced to

, because the last byte will always be 0.

• Nguyen

Hi nascardriver,

Output:

Mollie
╠╠╠╠╠╠╠╠╠
ollie
╠╠╠╠╠╠╠╠╠
llie
╠╠╠╠╠╠╠╠╠
lie
╠╠╠╠╠╠╠╠╠
ie
╠╠╠╠╠╠╠╠╠
e
╠╠╠╠╠╠╠╠╠

╠╠╠╠╠╠╠╠╠

At first I thought the same things as you explained in your reply that the address held in ptr (Let's say @ptr is 0xA7E0) was needed to keep looping as long as (ptr < 0xA7E7).  So I decided to make a small program to see what the real addresses of ptr and (name + arrayLength) are, but look at the output...something is not what I expected.

p/s:  Every time I edited, clicked "Save", all the code are no longer in the code tag.  That is why I have to re-post after editing.  Please try to see.

• nascardriver

> p/s
Refreshing the page fixes it, there's no need to re-post.

Both @ptr and @(name + arrayLength) are char*. When you pass a char* to @std::cout, it will be treated as a string.

If you want to print the pointer value as a number, you need to cast first

• Marcos O.

Hi nascardriver!

Thank you for this comment, does this mean @(name + arrayLength) resolves to an address when used by the program (ie. in the for loop) but to a string when used with std::cout? Is this different interpretation associated to compile time vs run time or am I completely off base?

Edit: how does @(name + arrayLength) compute, is @arrayLength implicitly converted to the same type as @name? @name is a char* pointing to the address of the first element of @name[] correct?

• Hi Marcos!

is a char*
It doesn't matter where it's used, it's always a char*
@std::cout knows that char pointers are used to represent strings. So instead of printing it as an address, it prints the characters that are being pointed to (A string is just an array of characters).
This isn't a special feature of the language, just how @std::cout is implemented.

• Marcos O.

Ok thanks! I think that clears things up quite a bit, so it remains the same type (char*) but is interpreted by @std::cout as string because a string is just an array of characters and @std::cout knows this? Is @arrayLength implicitly converted from int to char* when the computation occurs?

• > @std::cout knows this?
Correct

> implicitly converted from int to char* when the computation occurs?
any* + int = any*

• Marcos O.

Thanks! :)

• Omkar

const int arrayLength = 7;
char name[arrayLength] = "Mollie";
int numVowels(0);
for (char *ptr = name; ptr < name + arrayLength; ++ptr)
{
switch (*ptr)
{
case 'A':
case 'a':
case 'E':
case 'e':
case 'I':
case 'i':
case 'O':
case 'o':
case 'U':
case 'u':
++numVowels;
}
}

cout << name << " has " << numVowels << " vowels.\n";

for this example shouldn't the for loop termination condition be ptr < name + (arrayLength-1); ? Since the loop also checks the null terminator of the char array ? is that necessary

• Alex

Yes, we could optimize this by adding a -1, so it doesn't check the null terminator.

• Santi

Hi Alex,

Which is the diference between std::endl and "\n"?
I read it before in other chapter, but I can't find it.

Thank you for the tutorial and the support that you provide! :)

• nascardriver

Hi Santi!

When you use std::cout the input you give it is stored in a buffer. That buffer is regularly cleared and it's contents are displayed in the console. When you use '\n' the newline character will be inserted in the buffer and remain there until the next update occurs. When using std::endl the buffer is flushed immediately and your text is displayed.
'\n' is faster than std::endl but you might not see your text right away.
If you want to print multiple lines, you can use '\n' for every but the last line and use std::endl for the last line.

• Kushagra

#include <iostream>

int main()
{
const char *myName = "Alex";
std::cout << myName;

return 0;
}

• Kushagra

And why do you use const here?
what would be the result without const?

• Alex

"Alex" is a string literal. If myName was non-const, then you could try to modify "Alex", which will lead to undefined results. Making it const enlists the compiler's help in ensuring we don't try to modify the literal.

• Alex

"Alex" is a string literal. String literals have special handling. They are stored in a special part of memory, and are given a memory address. So you can initialize a char pointer with the address of a string literal.

• Kushagra

cout << name << " has " << numVowels << " vowels.\n";

in this , name is an array then why don't it outputs the address of its first element?

• Alex

Because std::cout has special handling for arrays of type char* or const char* that causes them to print as C-style strings instead.

• heyjuhua

hi alex, when i declare a pointer such as

can i say that ptr is the pointer pointing to a pointer? thanks

Also, one more question for the

you put arrayLength = 7 is that because of we need one more index for ''? Thanks so much !

• Alex

1) No. ptr is a pointer pointing to an array of 3 integers.
2) Yes, the array length needs to be large enough to hold the null terminator, otherwise crazy things will happen when we try to print the name or do anything else that is expecting the null terminator to be there.

• heyjuhua

• Ameen

ptr < name + arrayLength;

can you please explain me this line.

• heyjuhua

Hi, I think that means

the same thing. which is the array[0] + arrayLength so totally 7 indexes there. I am not sure if I am right.

• Alex

name is the address of the start of the array. arrayLength is the number of elements in the array. so name + arrayLength uses pointer arithmetic to find the address of the element that is just beyond the end of the array.

If ptr is initially set to name, then we can increment ptr to step through the array, and continue doing so as long as ptr < name + arrayLength. As soon as ptr == name + arrayLength, we know we've gone off the end of the array and should stop iterating.

• Ameen

thankyou for the reply....now i get it :)

• Ameen

alex can you please advice me some online websites or books which can help me in developing logical skills for programming

• Kushagra

correct me if i m wrong
as name is char ,when we increase the index by 1,  we increase the adress by 1
if it was integer we would use
ptr < name + (arrayLength*4);

• Alex

You are incorrect. When you increment a pointer, it automatically scales based on the type. So incrementing an integer pointer by 1 will increase the address by 4 (assuming 32-bit integers).

• Wouter

But sadly I still don't completely understand why this works.
Let me try to explain my confusion.

These are the memory addresses on my computer for the char array Mollie. (Pseudocode)

In the for loop we are checking if

So I assume the compiler knows how to cope with merging/counting hexadecimal and decimal? (I assume it compiles them both to binary so it doesn't really matter anyway).

But the question then is why is arraylenght, thus the decimal number 7 correct? Is it because a char is one byte? But if we would be using an int array. Would we then have to do arrayLenght*4? because the ++ptr knows it has to increment itself with 4 bytes to get to the next int address of the array? If not, then I am confused and still don't know why this works.

And a little remark. The example is missing

to print the results.

• Hi Wouter!

You must've made a mistake somewhere in your code while checking the addresses of each character. Each character is exactly 1 byte after the one before. Try this code:

Output on my machine

Now you get

> I assume it compiles them both to binary so it doesn't really matter anyway
Correct

> But the question then is why is arraylenght, thus the decimal number 7 correct?
> Is it because a char is one byte?
Because the array has 7 elements.

> But if we would be using an int array. Would we then have to do arrayLenght*4?
No. The loop loops over the elements, not the bytes. When looping through a string, an element and a byte is the same.

• Wouter

Sorry I still don't completely understand it. Thanks for the first information. It is helping.

Lets say we have an array of int's and we are looping through them.

this basically means

But because an int has 4 bytes the next int would be at address 0x7ffeefbff465 and the following at 0x7ffeefbff469 which is already surpassing the limit and thus we only get the first two values of the array.

So I would love to believe you and the explanation above, that it will work, but I don't understand why it works. Thanks again for all your effort! Greatly appreciated.

• You're right, I didn't check the loop when I replied.
You would indeed need to multiply the array length by sizeof(int). In practice, one would loop over the array via the index, not the pointer.

Looping over the pointer is sometimes done for strings.

• Wouter

This makes sense! Thanks for the clarification and the alternative solution.

• magaji::hussaini

Hi nas!
But I think the compiler will do the multiplication for you. take this snippet as an example:

As you can see, I dont multiply the literal '5' and each address differs by two just like alex said.

• Welp, I messed up again, thanks for pointing it out! The manual multiplication would only be necessary if @ptr was an integral type. But since it's a pointer, pointer arithmetic takes care of this for us.

Hello,

Why doesn't this work?

"No operator ">>" matches this operand:
operand types are: std::istream >> std::string"

• Alex

Works fine for me on Visual Studio 2017 and on the cpp.sh online compiler. Are you including the string header?

• shannon

So I was a bit confused with the switch loop, so I *think* I made it a bit more readable for some folks. Instead of declaring and initializing the ptr and declaring it inside the loop, it is outside now and just uses int i = 0 and i < arraylength (which equals 7). Hope this helps someone!

int main()
{
const int arrayLength = 7;
char name[arrayLength] = "Mollie";
int numVowels(0);
char *ptr = name;
for (int i = 0; i < arrayLength; ++i, ++ptr)
{
switch (*ptr)
{
case 'A':
case 'a':
case 'E':
case 'e':
case 'I':
case 'i':
case 'O':
case 'o':
case 'U':
case 'u':
++numVowels;
}
}

cout << name << " has " << numVowels << " vowels.\n";
return 0;
}