# 6.8 — Pointers and arrays

Pointers and arrays are intrinsically related in C++.

Array decay

In lesson 6.1 -- Arrays (part i), you learned how to define a fixed array:

To us, the above is an array of 5 integers, but to the compiler, array is a variable of type int. We know what the values of array, array, array, array, and array are (9, 7, 5, 3, and 1 respectively).

In all but two cases (which we’ll cover below), when a fixed array is used in an expression, the fixed array will decay (be implicitly converted) into a pointer that points to the first element of the array. You can see this in the following program:

On the author’s machine, this printed:

```Element 0 has address: 0042FD5C
The array decays to a pointer holding address: 0042FD5C
```

It’s a common fallacy in C++ to believe an array and a pointer to the array are identical. They’re not. In the above case, array is of type “int”, and its “value” is the array elements themselves. A pointer to the array would be of type “int *”, and its value would be the address of the first element of the array.

We’ll see where this makes a difference shortly.

All elements of the array can still be accessed through the pointer (we’ll see how this works in the next lesson), but information derived from the array’s type (such as how long the array is) can not be accessed from the pointer.

However, this also effectively allows us to treat fixed arrays and pointers identically in most cases.

For example, we can dereference the array to get the value of the first element:

Note that we’re not actually dereferencing the array itself. The array (of type int) gets implicitly converted into a pointer (of type int *), and we dereference the pointer to get the value at the memory address the pointer is holding (the value of the first element of the array).

We can also assign a pointer to point at the array:

This works because the array decays into a pointer of type int *, and our pointer (also of type int *) has the same type.

Differences between pointers and fixed arrays

There are a few cases where the difference in typing between fixed arrays and pointers makes a difference. These help illustrate that a fixed array and a pointer are not the same.

The primary difference occurs when using the sizeof() operator. When used on a fixed array, sizeof returns the size of the entire array (array length * element size). When used on a pointer, sizeof returns the size of a memory address (in bytes). The following program illustrates this:

This program prints:

```20
4
```

A fixed array knows how long the array it is pointing to is. A pointer to the array does not.

The second difference occurs when using the address-of operator (&). Taking the address of a pointer yields the memory address of the pointer variable. Taking the address of the array returns a pointer to the entire array. This pointer also points to the first element of the array, but the type information is different (in the above example, the type of `&array` is `int(*)`). It’s unlikely you’ll ever need to use this.

Revisiting passing fixed arrays to functions

Back in lesson 6.2 -- Arrays (part ii), we mentioned that because copying large arrays can be very expensive, C++ does not copy an array when an array is passed into a function. When passing an array as an argument to a function, a fixed array decays into a pointer, and the pointer is passed to the function:

This prints:

```32
4
```

Note that this happens even if the parameter is declared as a fixed array:

This prints:

```32
4
```

In the above example, C++ implicitly converts parameters using the array syntax ([]) to the pointer syntax (*). That means the following two function declarations are identical:

Some programmers prefer using the [] syntax because it makes it clear that the function is expecting an array, not just a pointer to a value. However, in most cases, because the pointer doesn’t know how large the array is, you’ll need to pass in the array size as a separate parameter anyway (strings being an exception because they’re null terminated).

We lightly recommend using the pointer syntax, because it makes it clear that the parameter is being treated as a pointer, not a fixed array, and that certain operations, such as sizeof(), will operate as if the parameter is a pointer.

Recommendation: Favor the pointer syntax (*) over the array syntax ([]) for array function parameters.

An intro to pass by address

The fact that arrays decay into pointers when passed to a function explains the underlying reason why changing an array in a function changes the actual array argument passed in. Consider the following example:

```Element 0 has value: 1
Element 0 has value: 5
```

When changeArray() is called, array decays into a pointer, and the value of that pointer (the memory address of the first element of the array) is copied into the ptr parameter of function changeArray(). Although the value in ptr is a copy of the address of the array, ptr still points at the actual array (not a copy!). Consequently, when ptr is dereferenced, the element accessed is the actual first element of the array!

Astute readers will note this phenomena works with pointers to non-array values as well. We’ll cover this topic (called passing by address) in more detail in the next chapter.

Arrays in structs and classes don’t decay

Finally, it is worth noting that arrays that are part of structs or classes do not decay when the whole struct or class is passed to a function. This yields a useful way to prevent decay if desired, and will be valuable later when we write classes that utilize arrays.

In the next lesson, we’ll take a look at pointer arithmetic, and talk about how array indexing actually works. 6.8a -- Pointer arithmetic and array indexing Index 6.7a -- Null pointers

### 233 comments to 6.8 — Pointers and arrays

• Samira Ferdi

What is the meaning of copied value and actual value? These terms make me confuse!

• GHG

If the array of a struct or class gets passed into a function, does it decay?

• Alex

Yes.

• Haider

I have three queries.
Why does the pointer point to the first element in the initial array?
Can we find all the addresses of each variable in a multi-dimensional array?
What's the difference between a pointer and a pointer variable?

• nascardriver

Hi Haider!

> Why does the pointer point to the first element in the initial array?
Because it's defined to do so.

> Can we find all the addresses of each variable in a multi-dimensional array?

> What's the difference between a pointer and a pointer variable?
How I understand at

• Nguyen

Hi,

Output:

007AF9F8
999
2
007AF9F8
999
2

Please take a look at lines 7 & 17.  I've seen prt and *prt in the examples over and over from 6.7 to 6.8.  I came up with this small program, here something new I've learned.

• Nguyen

"When changeArray() is called, array decays into a pointer, and the value of that pointer (the memory address of the first element of the array) is copied into the ptr parameter of function changeArray(). Although the value in ptr is a copy of the address of the array, ptr still points at the actual array (not a copy!). Consequently, when ptr is dereferenced, the actual array is dereferenced!"

So based on the program I created, lines 5 & 6 are the examples of what the above paragraph is all about.  But line 7 is not mentioned in anywhere.  I don't even know if it has a name or it is valid.  Please let me know what line 7 is all about?

Thanks, Have a great day

• nascardriver

Hi Nguyen!

When an array decays into a pointer it looses it's type information (ie. the size information), but the pointer still points to the array.

• Nguyen

Hi nascardriver,

Since they are equivalent when the function is called, it makes sense that we can print prt (line 7) in the called function.

How's about line 17 in the main function?
We can print prt because prt is equivalent to array? That's why prt[0 or 1 or 2...] is also equivalent to array[0 or 1 or 2....]?

• nascardriver

Line 13 does the same to the array as the call to @doSameThings does. The array decays into a pointer, loosing only it's type information, the array persists.
The array syntax (a) isn't unique to arrays, you can use it on any pointer as well. It only really makes sense with arrays though.

> prt is equivalent to array
It's not equivalent, but they both point to the same data, so they behave equivalent _for the most part_.

• Nguyen

Hi,

Looks like the address-of operator (&) is not required to allows us to see what memory address is assigned to an array.  I don't know why it is inconsistent with others.

• nascardriver

Hi Nguyen!

The value of an array is a pointer to the first element. Line 3 is equivalent to

• Nguyen

Hi nascardriver,

All the outputs are the same.  If I saw &array instead of array in the first example in the lecture, I would not have any question.

• Nguyen

Output:

008FF750
008FF750
008FF750

9
008FF750 // I expected to see 9.  Why the address is here?
9

• nascardriver

Line 3 and 4 print the same value, because the pointer to the first element (line 3) is the same as the address of the array itself (line 4).

Line 10: array is an int*.
Dereferencing @array in line 10 gives you the value of the first element.
Line 11: &array is an int(*), dereferencing that gives an int*. (*&a is equivalent to a, unless operator& has been overloaded).

Sorry if this doesn't help you out, I barely understand it myself. If Alex could elaborate here, that'd be great.

• Nguyen

Here's what I am thinking about *&array.

1.  The array has address 008FF750 (array is equivalent to &array)- OK
2.  The &array has address 008FF750. Again, array is equivalent to &array, this means &array = &(&array).  What is &(&array)?  I don't think it even exists at least at this point. I don't understand why &array even has the address.
3.  *&array = array (back to no.1, array's address is 008FF750; therefore, *&array = 008FF750) -

Here's what I understand about *array:
Every time I see *array, I think it as *array = *&array (array = &array).  This helps me to understand why *array is 9 as an output.

I think it is better for me to move on without thinking about &array.  Is &array legal anyway?

• nascardriver

> array is equivalent to &array
Nope, but very similar.

> Is &array legal anyway?
Yes it is, the code wouldn't compile otherwise. But I don't see in which situation is would be useful.

• seriouslysupersonic

Hi!

I understand that when we apply the address-of operator to an array we get a pointer to the entire array which is of type: typename(*)[array_length] and that we will likely never need it. However, I wanted to understand how can we actually declare it.

This program works, but I would like to declare the pointer to the entire array without using type inference. How should I do it?

This produces:

Pointer to entire array
type  PA5_i
array 1
array 2
array 3

• nascardriver

• seriouslysupersonic

Appreciated!

• David

Hi! Suppose I want to assign an array to another array. Something like this doesn't work:

I could use pointers, but that could be dangerous because there's no size compatibility checking. What's the best way to do this? And is there a way to do it with std::array and std::vector?

• nascardriver

Hi David!

If you did a pointer copy you wouldn't actually copy the array, you'd be creating an alias.

Prints 19

Once you've created an array with a specific size there's no way to resize it. You'd need to dynamically allocate a new array and copy each element to the new array. See lesson 6.9a.

std::array and std::vector can be copied by using the operator=.

• Reader

Note that this happens even if the parameter is declared as a fixed array:

This prints:

32
4

I do not understand at all how 32 and 4 are arrive at.

• nascardriver

On the machine used to run the code above sizeof(int) is 4 and sizeof(int *) is 4 too.
The sizeof call in line 13 returns the sum of the sizes of all elements in the array. That is 8 * 4 = 32 (8 elements, 4 bytes each).
When passing an array as argument it will decay to a pointer. This means that the sizeof operator will no longer returns the sum of the sizes of all elements but the size of the pointer instead. Since the array parameter is an int* the sizeof operator returns 4.

• david

Hi Alex, if array points to the first element why &array gives the same address as the first element

• Alex

In C++, built-in arrays don't have any overhead (they just have different type information). Therefore, the start address of the array is identical to the start address of the first element!

• prince GUPTA

Alex you have quoted   "because the pointer doesn’t know how large the array is, you’ll need to pass in the array size as a separate parameter anyway (strings being an exception because they’re null terminated)."

please can you provide an example for strings holding this exception.

• nascardriver

Hi price GUPTA!
Let's look at what an array is in memory,

The  in the end of "Hello" makes the difference, it's a byte with the value 0. If you look at an ASCII table you'll see that 0 isn't a character, it's used to mark the end of a string. This way, your program can keep reading characters from memory until it finds 0, then it know it found the end of the string.
For normal arrays this can't be done, because 0 could just as well be an element of the array.

The @strlen function makes use of this, you pass it you char *, in this case @szText, and it will walk through the string until it finds 0. With every step it takes it increases a counter by one. By the time the 0 has been found the counter will hold the strings length.

• Alex

Here's code to print an integer array. We need to pass the array's length since we can't tell where the array ends.

But for strings, we can rely on the presence of the '\0' char (0) to denote the end of the array. So if we're just iterating through the array, we can iterate until we hit the '\0', like this:

• Dusty

Hi Alex,
Thanks a lot for the tutorial.
At the very first example of this part I feel like instead of
std::cout << "The array has address: " << array << 'n';
It should be
std::cout << "The array has value: " << array << 'n';

I haven't read the rest. I hope I am not bothering.

• Alex

Well, since arrays decay to pointers when evaluated, in this context, array decays to a pointer to the array. And since the pointers hold addresses, we can say the value of a pointer is an address. So, I think either is probably appropriate.

• Yahya

Hello dear Alex and thank you very much for this great site.
First of all I apologize for the weakness of my English ..

I want to declare a function prototype for printing a 2dArray in a header file (and define a function to permanent use). I searched the Internet but I didn't get the appropriate answer because they mostly printed the array in the main function and I didn't want that.
If I use the following syntax:

or:

(note: ==> (int arr[][], int row, int col) this is the method that came to my mind for having row and column values in the function.)

the compiler will gives this error:
`error: multidimensional array must have bounds for all dimensions except the first`

Yes it's true but I can not put a number in the second [] in a header file!
What should I do to fix this problem?

Thanks again and good luck...

• Yahya

Since it was said: "Arrays decay into pointers when passed to a function"
this is the only way that I could do without causing error:

in .cpp file for implementing:

and in main file:

unfortunately in this code I must use *arr while calling print2DArray...
any other ways that I tried, resulted in an error.(e.g. int**)

Thanks a lot.

• Yahya

:D

• Alex

Read lesson 6.14 and see if that's helpful in figuring it out. If not, ask again there.

• Yahya

Thank you very much...

• Harpreet Kaur

I am running these 2 statements:

std::cout << sizeof(int);
std::cout << sizeof(int*);
Both of these should print 4 bytes(if compiler take 4 bytes for int)
but sizeof(int) is printing 4
and sizeof(int*) is printing 8

• Alex

You are using a 64-bit address space, so your integer pointers are 8 bytes in size so your addresses are 64 bits in size.

• Joseph

Now I understand why my passing an array to a function didn't work! hahaha.. I tried to create a function to accept an array for Chapter 6 lesson 3 quiz and I didn't understand the result so I had to dump the function and create the instructions inside main(). but I modified it now and it works fine. Chapter 6 Lesson 3 Quiz 2.

void printArrayAndIndex(int *array, int number, int arrayLength) {
for (int i = 0; i < arrayLength; ++i)// prints the array using pointer
std::cout << *(array+i) << " ";
std::cout << "\n";
for (int i = 0; i < arrayLength; ++i)// finding the index of the number given using pointer
if (*(array+i) == number)
std::cout << "Your number is at " << i << " index. \n";
}

• Hardik

Here also, the array being passed doesn't decay, no?
Because then we wouldn't have been able to change all of the elements of the array.

• Alex

The array does decay into a pointer when passed to the function. However, we can still use the pointer to modify the original array argument.

• Hardik

It means that the function parameter is also a pointer that is capable of holding the memory address of the array being passed !

• C++

Output :-
0x60ff08
0x60ff08
0x60ff08

Output :-
0x60ff0c
0x60ff0c
0x60ff08

Why The Outputs are different?
Is it because it(in the 2nd case) produces the memory address of the ptr var rather than the var it is pointing to? Plz Explain !

• Alex

In the last example, you're printing the address of variable ptr, not the address that ptr is holding (which is array's address). It should be consistent if you change to this:

• C++

"Is it because it(in the 2nd case) produces the memory address of the ptr var rather than the var it is pointing to?"

I said that btw ! But, Thanks :) !
No, I just wanted to experiment it !

• James Ray

The confusion is primary
The confusion is primarily

• Alex

Fixed, thanks!

• nikos-13

a) "When evaluated, a fixed array will “decay” into a pointer to the first element of the array. All elements of the array can still               be accessed through the pointer, but information derived from the array’s type can not be accessed from the pointer."

What do you mean with "All elements of the array can still be accessed through the pointer", how could this happen?

b) " Taking the address of the array returns a pointer to the entire array. This pointer also points to the first element of the array, but the type information is different (in the above example, int(*))."

What do you mean with "int(*)"?

• Alex

1) I mean a pointer pointing at the first element of an array can be used just like the array itself can. For example:

This works because of pointer arithmetic.

2) Don't worry about it for now. It's not something you need to know to progress.

• nikos-13

Thank you Alex!

• Nguyen

Hi Alex,

The last line (std::cout << ptr; // will print 3 (value of element 1) is so strange to me.

In this chapter, I only see std::cout<<ptr & std::cout<<*ptr in the examples.

• Alex

We cover that usage in the very next lesson.

• Nguyen

Hi Alex,

I've finished 6.8B & I don't see it????  I don't want to miss it.

Thanks, Have a great day.

• Alex

I was referring to 6.8A, particularly the subsection titled, "Pointer arithmetic, arrays, and the magic behind indexing"

• Nguyen

Hi Alex,

Based on what I've learned from 6.8A, it would make sense to me if the last line looked like in the following:

int array[] = { 5, 3, 6, 7 };
int *ptr = array;
std::cout << array; // will print 3 (value of element 1)
std::cout << *(ptr + 1); // will print 3 (value of element 1)

=====================================================

Oh ok, I think I understand it now.

array[n] is the same as *(array + n); therefore, *(prt + 1) is the same as prt. Yah!

To me, prt seemed very strange to me at first because I did not see it in the lesson.  It would be nice if it somehow was seen/mentioned in the examples.

Thanks, Have a great day.

• thang

Why ???? it still printed 4

//Finally, it is worth noting that arrays that are part of structs or classes do not decay when the whole struct or class is passed to a function. This yields a useful way to prevent decay if desired, and will be valuable later when we write classes that utilize arrays.

#include

struct new1
{
int a;
};

void printsize(new1 arr[]);

int main()
{
new1 arr;
printsize(arr);
}
void printsize(new1 arr[])
{
std::cout << sizeof(arr) << "n";
}

• Alex

You created an array of structs rather than a struct containing an array.

• thang

// it is worth noting that arrays that are part of structs or classes do not decay when the whole struct or class is passed to a function.//

I don't understand why you said arrays do not decay when struct is passed to a function but in above code arr still has size is 4 provide that it decays in pointer...

sorry for my bad english .))

• Alex

Because you're code isn't doing what I'm suggesting. :) An array that is inside a struct will not decay:

An array of structs will still decay:

• thang

Oh thanks Alex, you are very enthusiastic

• Rohit

Is there any way of passing and array into a function without decaying it except using struct or classes or some other thing, just passing it through main()?

• Alex

Yes, there is. You can pass an array by reference:

But the syntax is messy. A better solution is just to use std::array. We cover std::array later in this chapter.

• Milos

Alex love your site so much it helped me a lot, i have one off topic quesiton,
I have searched today a little bit on the internet and found out that visual studio 2012+ don't support windows form applications, i also found out there is a way to go around it but i dont have a tools menu or things like that (if u understand me), so my questions are how do i create real life applications for windows with c++ and where also can i use my c++ knowledge for creating some real life programs?

Thank you for everythig, you are the real HERO <3

• Alex

My understanding is that Windows Form applications are part of Microsoft .net, so you need to use managed C++ to create one. Unfortunately, I don't have any knowledge on that topic, as I've never used .net (outside of some dabbling with C#).

• Chrisenyle

Hi, Alex
I have a question for you. Give this code:

...

....

I know this will print 20 (NumberOfElements * sizeof(int))
But I want to ask that how can it know the size of the array?
'Who' is holding the information of the array's length?

Thanks

• Alex

When you compile your program, the compiler builds a symbol table full of variable names and types as it encounters variables. The sizeof operator is resolved at compile time, and the size itself can be derived from the variable's type. So when you compile this program, the compiler will replace "sizeof(array)" with 20 (which it knows because it knows that array is an array of 5 integers).

• Chrisenyle

Thank you very much!
You are amazing!

• raj

Thanks Alex.

• raj

why is my code failing?
int* test();
int main()
{
int* ptr=test();
for(int i=0;i<3;i++)
cout<<*(ptr+i)<<" ";

}
int* test()
{
int arr;
arr=10;
arr=20;
arr=30;
return arr;

}

i am getting some garbage output instead of actual values in the array

• Alex

Variable arr is a local variable. That means it goes out of scope (and is destroyed) at the end of test.

However, you're passing the address of arr back to main(). By the time main() gets the address, arr has already been destroyed. Consequently, main() is accessing a pointer that is now pointing to garbage.

• bert

I think there's an extra word this time:

and we dereference the pointer to get the value at that the memory address the pointer is holding

I think you meant to drop the "that"

thanks!

• kris

First I'd like to thank you for this great site teaching everything about c++. But my problem is i want to learn everything how to write the program use a command prompt and eventually become good to able to code my own video games. I have more then 15 hours a day and this is great. Please provide a learning path or what to do or etc. So I'll has a good perceptive of it all.

I believe you have my email thanks!!!! krisgoku2@hotmail.com

• Raquib

Hey Kris,

I am glad to see that you are passionate about learning how to code bottoms up, that's necessary to start learning anything generally. I am not an expert but I might be able to share with you some suggestions that I received from many programmers over the years -

1- Get your hands dirty- Just start coding. This site can help you with that. Do the exercises/quizzes at the end of the chapters to begin with. Learn a concept and apply it. Man everyone starts with a hello world. Every single programmer I came in touch with said me the same thing. Follow the best practices in every code you write until it becomes your second nature. So, to quote from a fender squier affinity series slogan "stop dreaming, start playing" :) .

3- Aim small miss small (from Patriot) - Don't expect to learn everything in one day. Start slow, have small goals don't rush. Since you have a lot of time, make sure you complete each chapter properly. Don't jump coz these lessons have been organized after a lot of time spent on how to do it.  These concepts are very important and will teach you the core C++. Once done you will be capable enough to absorb new concepts and more advanced topics. Which will require time, and lots of coding experience.

Best of luck. Happy coding :)

Regards,
Raquib

• Purna

Hi Alex,

I have a Query. I am Checking the below Program.

#include <iostream>

int main()
{
using namespace std;
int array = {1,6,9,5,7};

std::cout << &array << "n" << &array;
std::cout << '\n';
std::cout << *(&array) << "n" << *(&array);
return 0;
}

When I run this program, I got the address for the first element of the array in both the cases(for the first cout). I understand the reason, As you rightly said: "The only difference is the type information that is returned. A pointer to the first element would have type int*, whereas a pointer to the whole array would have type (int *).".

However, for the third cout, I am trying to dereference "&array" and "&array".

So while dereferenceing, For "&array", I got the correct result, i,e 1.
But for "&array", I got the memory address of the "array" again after dereferencing in stead of the array element.

I couldn't understand the reason for this. Could you please explain, why *(&array) evaluated to memory address of the array rather then value of the array ?

• Alex

Remember that array decays to a pointer of some kind, and [] has an implicit deference. So:
*(&array) evaluates array, giving you the value of element 0, which you then take the address of (giving you a pointer), which you then dereference to get the value of element 0 again.
*(&array) evaluates &array, which takes the address of the pointer to the array, essentially giving you a pointer to a pointer. You then dereference this to get back the original pointer to the array. This is why you're getting an address here.

On the left hand side, *array dereferences the pointer to the array, giving you the value of element 0.

• Jason

What do you think of the following syntax for passing arrays to a function?

• Alex

It generally won't work, unless arraySize is a macro. arraySize has to be a integer literal -- strangely enough, constexpr variables don't seem to work here.

• abolfazl

• Darren

I remember there being some obscure syntax about arrays. Something like that myArray[n] is equivalent to *(myArray + n) which is equivalent to *(n + myArray) such that a statement like n[myArray], where n is an integer representing an array index, is actually valid syntax for access to the (n - 1)th array element. Not that you'd want to use such an odd thing.

• Alex

This is covered in the very next lesson. :)