Why arr, &arr, and arr[0] Aren’t the Same in C++

Santwan PathakSantwan Pathak
8 min read

Introduction


If you’ve worked with arrays and pointers in C++, you might have noticed some confusing behavior. For example, arr == &arr[0] works fine, but int* p = &arr; throws an error. In this post, I’ll explain what’s going on behind the scenes with simple examples, why these things behave differently, and how pointers actually work with arrays.


1. What is an Array in C++?

When you declare:

int arr[] = {3, 45, 6, 78, 89, 9, 0};

You're telling the compiler to:

  • Allocate 7 consecutive memory locations, each capable of storing an int.

  • Name the starting point of this block as arr.


2. How Arrays Relate to Pointers

💡
arr itself acts like a constant pointer to the first element, meaning arr == &arr[0].

You can assign the array name to a pointer:

int* p1 = arr;         // ✅ valid
int* p2 = &arr[0];     // ✅ valid

Both p1 and p2 now point to the first element of the array (arr[0]).

cout << p1 << endl;    // prints address of arr[0]
cout << &arr << endl;  // prints address of the entire array (same address, different type!)
cout << &arr[0] << endl; // prints address of arr[0]

Though &arr and &arr[0] may print the same value, they are not the same in type.

Key Type Differences

ExpressionTypeMeaning
arrint*Pointer to the first element
&arr[0]int*Address of the first element
&arrint (*)[7]Pointer to the entire array

Think of &arr as: “Here’s the whole array block.”
Think of &arr[0] or arr as: “Here’s where the block begins.”


❌ 3. The Wrong Way: int* p = &arr;

It may be completely valid for variables but this is complete opposite of that

int* p = &arr; // ❌ Invalid!

This leads to a type mismatch, because:

  • &arr is of type int (*)[7] (pointer to array of 7 integers)

  • p is of type int* (pointer to a single int)

Even though both arr and &arr may point to the same address, they are fundamentally different in what they point to.

Trying to use int* p = &arr; will either:

  • Fail to compile, or

  • Work with unsafe behavior (e.g., pointer arithmetic won't work as expected)


4. Correct Way to Get Array’s Address

If you really want to point to the entire array, you should write:

In most real-world cases, you just need a pointer to the first element:

int* p = arr;        // ✅ Common and clean

🛑 5. Don’t Do This: Assigning a Value to a Pointer

int* p = arr[0]; // ❌ WRONG!

Why this fails:

  • arr[0] is the value stored in the array (like 3), not its address.

  • You're trying to store an int into an int* (pointer) → invalid!


7. Using Pointers to Traverse, Access, and Modify Array Elements

Pointers aren't just for accessing the first element. Once you have a pointer to the start of an array, you can:

Traverse the array
Access each element
Modify elements directly — without using array indexing (arr[i])

But... Why Use Pointers Instead of Indexes?

Using pointers gives:

  • More control over memory.

  • Efficient low-level access (important in systems programming).

  • Better performance in some cases (like iterators in STL).

  • It's a must for dynamic memory (new[], malloc(), etc.).

How to Traverse an Array Using Pointers

#include <iostream>
using namespace std;

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;  // Same as &arr[0]

    cout << "Accessing array using pointer:\n";

    for (int i = 0; i < 5; i++) {
        cout << "Element " << i << ": " << *(ptr + i) << endl;
    }

    return 0;
}

💡 Explanation:

  • ptr points to arr[0]

  • *(ptr + i) gives the value at arr[i]

  • ptr + i moves the pointer to the ith memory location

✅ This is called pointer arithmetic


Modifying Array Elements with Pointers

Let’s say you want to double all elements of an array:

#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int* ptr = arr;

    for (int i = 0; i < 5; i++) {
        *(ptr + i) *= 2;  // Modify value at each location
    }

    cout << "Modified array:\n";
    for (int i = 0; i < 5; i++) {
        cout << arr[i] << " ";  // Now shows: 2 4 6 8 10
    }

    return 0;
}

🧩 Summary: What You Can Do With Pointers to Arrays

OperationExampleDescription
Access*(ptr + i)Access the value at arr[i]
Modify*(ptr + i) = x;Change the value at arr[i]
Traverseptr++ in loopMove from one element to next
Range Loopwhile (ptr < arr+N)Loop from start to end via pointer

Bonus Insight: ptr[i] Works Just Like arr[i]

Once you have a pointer to the beginning of the array:

int* ptr = arr;

You can absolutely use:

ptr[i]  // same as *(ptr + i)

This works because in C++, array indexing is just syntactic sugar over pointer arithmetic.

ptr[i] is defined as *(ptr + i)
arr[i] is defined as *(arr + i)

Even cooler:

i[arr] == arr[i]  // damnnn this is true!

Why This Works?

Because array subscript notation is defined like this:

cppCopyEdita[b]  ≡  *(a + b)

So whether arr is the array or ptr is a pointer:

  • ptr[i] → gets the value at offset i from the pointer

  • ptr[i] = 100 → modifies that value


✅ Updated Example Using ptr[i] Directly:

#include <iostream>
using namespace std;

int main() {
    int arr[] = {5, 10, 15, 20};
    int* ptr = arr;

    for (int i = 0; i < 4; i++) {
        cout << "Value at index " << i << ": " << ptr[i] << endl;
    }

    // Modifying values using pointer
    for (int i = 0; i < 4; i++) {
        ptr[i] *= 2;
    }

    cout << "Modified array:\n";
    for (int i = 0; i < 4; i++) {
        cout << arr[i] << " ";  // Output: 10 20 30 40
    }

    return 0;
}

Conclusion: Your Final Pointer Options

ExpressionPurpose
ptr[i]Access using array-style syntax
*(ptr + i)Access using pointer arithmetic
ptr++Move to next element (use with care!)

Both styles are valid. Which one to use depends on:

  • Readability

  • Performance (negligible difference in most cases)

  • Personal or team preference


7. Memory Layout: Visualized

Here’s how your array looks in memory:

cssCopyEditAddress     Value
0x1000      3     ← arr[0]
0x1004      45    ← arr[1]
0x1008      6     ← arr[2]
...         ...

Now,

  • arr or &arr[0] → points to 0x1000

  • arr + 1 or &arr[1] → points to 0x1004

  • And so on...

So you can do pointer arithmetic:

int* p = arr;
cout << *(p + 2); // Output: 6 (arr[2])

🔚 Final Summary Table

ExpressionValid?Meaning
int* p = arr;Pointer to first element
int* p = &arr[0];Also pointer to first element
int* p = &arr;Type mismatch (&arr is pointer to whole array)
int (*p)[7] = &arr;Pointer to the entire array
int* p = arr[0];Invalid: assigning int to int pointer

Complete Working Example

#include<iostream>
using namespace std;

int main() {
    int arr[] = {3, 45, 6, 78, 89, 9, 0};

    int* p1 = arr;
    cout << "p1 (arr): " << p1 << endl;

    cout << "&arr: " << &arr << endl;
    cout << "&arr[0]: " << &arr[0] << endl;

    // int* p2 = arr[0]; // ❌ Error: assigning int to pointer

    int* p3 = &arr[0];
    cout << "p3 (&arr[0]): " << p3 << endl;

    // int* p4 = &arr; // ❌ Invalid, explained above

    int (*p5)[7] = &arr; // ✅ Pointer to the whole array
    cout << "p5 (&arr): " << p5 << endl;
    cout << "(*p5)[2] (arr[2]): " << (*p5)[2] << endl;

    return 0;
}

Conclusion

Understanding the small but important differences between arr, &arr, and arr[0] helps you build a solid grasp of how arrays and pointers behave in C++. These are not just minor syntax details — they affect how your code works at the memory level. Knowing how pointers interact with arrays makes it easier to debug pointer-related issues, write cleaner code, and handle more advanced concepts like pointer arithmetic, dynamic memory allocation using new and delete, working with functions that take pointers as arguments, and even low-level tasks like writing your own data structures or memory-efficient code. If you’re planning to go deeper into system programming or just want to be confident with C++, this is one of the fundamentals you can’t skip.

0
Subscribe to my newsletter

Read articles from Santwan Pathak directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Santwan Pathak
Santwan Pathak

"A beginner in tech with big aspirations. Passionate about web development, AI, and creating impactful solutions. Always learning, always growing."