DEV Community

Cover image for The confusing Pointers and Arrays in C++
Shreelaxmi Hegde
Shreelaxmi Hegde

Posted on • Edited on

The confusing Pointers and Arrays in C++

Introduction
When I started learning C++, pointers felt like black magic especially when working with arrays. Array and pointer concepts and their flow felt confusing.

While solving an array-based question, I ran into this bug:

❗ 'sizeof' on array function parameter 'arr' will return size of 'int*'

So I paused and went back to revise pointers and boom, things started clicking magically! Suddenly, the flow of logic made much more sense.

Here’s everything I learned, explained in the simplest possible way.


What Is a Pointer?
A pointer is a variable that stores the memory address of another variable.

Example:

int a = 10;
int* ptr = &a;  // pointer variable storing address of a
Enter fullscreen mode Exit fullscreen mode
  1. &a → gets the address of variable a
  2. ptr → stores that address
  3. *ptr → gives the value stored at that address (dereferencing)

Two Uses of the Asterisk *

The symbol * is used in two ways:

  1. Declaring a pointer: int* ptr;

  2. Dereferencing a pointer: cout << *ptr;


NULL Pointer

A null pointer is a pointer that doesn’t point to any memory location.

int* ptr = NULL; // or int* ptr = 0;

  • NULL points to address 0x0
  • You can’t dereference a null pointer. Doing cout << *ptr; will result in a runtime crash.
  • Note: Just declaring int* ptr; without initialization gives a garbage address.

Array as a Pointer

int arr[] = {1, 2, 3};

  • arr is actually a constant pointer to the first element (&arr[0])
  • *(arr + 1) is the same as arr[1]
  • But remember: You cannot do arr = &x; because array names are non-modifiable lvalues (fixed memory pointers).

Passing Arrays to Functions

When you pass an array to a function, it acts as a pointer. That means only the address of the first element is passed, not the whole array.

void print(int arr[]) {
    // arr is actually int* inside the function
}
So sizeof(arr) will give size of int*, not the full array.
Enter fullscreen mode Exit fullscreen mode

How to Handle It?

Always pass the array size separately to functions:

void print(int arr[], int size) {
    for (int i = 0; i < size; i++)
        cout << arr[i] << " ";
}
Enter fullscreen mode Exit fullscreen mode

Key Insights Where Most Beginners Get Confused:

int a = 10;
int* ptr = &a;
cout << &a << " = " << ptr; → Both print the memory address of a

cout << a << " = " << *ptr; → Both print the value stored at that address → 10

*ptr = 20; → Modifies the value of a to 20
Enter fullscreen mode Exit fullscreen mode

Reference Variables

A reference is just another name for an existing variable.

int a = 10;
int& b = a;

cout << a << " = " << b;  // Both print 10
a and b refer to the same memory location.
//Any change to one affects the other.
Enter fullscreen mode Exit fullscreen mode

Pass by Reference

You can pass variables by reference to a function so that any changes affect the original value:

void func(int& a) {
    a = 50;  // changes the actual argument
}
Enter fullscreen mode Exit fullscreen mode

This avoids copying the variable


Summary
int* ptr = &a; → pointer stores address
*ptr → gets value at that address
arr is a constant pointer to the first element
Arrays decay into pointers in function calls
Always pass size with arrays
Use NULL to safely initialize unused pointers
Reference variables (int &ref = var;) refer to the same memory
Pass by reference reflects changes in the original argument


Final Thoughts

Pointers and arrays are scary at first, but once you understand what’s really happening under the hood (just memory addresses and values), it becomes easier to work with them.

If you're just starting out in C++, I hope this helped you get one step closer to mastering them.

Have questions or got stuck somewhere similar? Drop a comment — let’s grow together!

Top comments (9)

Collapse
 
pgradot profile image
Pierre Gradot

int arr[] = {1, 2, 3};
arr is actually a constant pointer to the first element (&arr[0])

This is not exactly true. arr is the pointer. But almost everywhere you write arr, the compiler implicitly replaces it with a pointer to its first element.

You almost said it later in the article :

Arrays decay into pointers in function calls

It's not just in function calls.

Here is a quote from the C99 standard:

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Collapse
 
dshree profile image
Shreelaxmi Hegde • Edited

You're absolutely right. thanks a lot for pointing that out! 🙌

I did oversimplify it by calling arr a constant pointer. As you explained, arrays decay into pointers in most contexts, not just in function calls, and your reference to the C99 standard really makes that clear. I genuinely learned something new from your comment. appreciate you taking the time to share it! 😊

Collapse
 
pgradot profile image
Pierre Gradot

A long time ago, I also run into a situation where I got really puzzled by a code when the difference between arrays and pointers really mattered. This is one of biggest trap in C IMHO....

I wrote a blog post back then gradot.wordpress.com/2012/08/08/de... and regularly quote it XD

Thread Thread
 
dshree profile image
Shreelaxmi Hegde

That sounds really interesting. I’d actually love to read your blog post, even if it’s in another language! I tried to translate it but couldn’t find a way that worked well.
If you ever get a chance to share an English version (even a rough one), I’d be genuinely interested. These subtle differences in C/C++ always make for great learning! 😊

Thread Thread
 
pgradot profile image
Pierre Gradot • Edited

I tried deepl.com/en/translator and the translation seemed really good. It even translates the code! Tell me what you think.

Thread Thread
 
dshree profile image
Shreelaxmi Hegde • Edited

Hey,
It took a little long to respond.
I read the shared documentation multiple times. And it cleared some small small doubts (like I had no idea, why pointer and &pointer will give different outputs. Just thought those were garbage values pointing to random memory, array initialized with string don’t decay to pointer, etc.) and my understanding on the array and pointers relation and their internal flow become more clearer and connected some more points. Now all things making sense.
I also learned about multidimensional arrays which is a new topic to me.
I’m very very thankful to you for sharing such a valuable asset.

The tool you suggested was really **helpful **and worked perfectly.

Thread Thread
 
pgradot profile image
Pierre Gradot • Edited

Gald it helped :)

Just thought those were garbage

I guess there is no such thing in a well-formed program.

A pointer must be stored somewhere and hence it must have an address. This is why you can have a pointer to pointer to something.

A an array must also be stored somewhere and have an address. And have pointer to an array of something:

#include <iostream>

int main() {
    int array[10] = {};
    printf("%p\n", &array);
    printf("%p\n", array);
    printf("%p\n", &array[0]);

    int (*pointer)[10] = &array; // --> auto in C++ is of course better
    printf("%p\n", pointer);

    int (**pointer_to_pointer)[10] = &pointer; // auto even better!
    printf("%p\n", &pointer_to_pointer);
}
Enter fullscreen mode Exit fullscreen mode

This code prints (for instance):

0x7ffe642240a0
0x7ffe642240a0
0x7ffe642240a0
0x7ffe642240a0
0x7ffe64224098
Enter fullscreen mode Exit fullscreen mode

The more you play with this the more it will make sense.

Thread Thread
 
dshree profile image
Shreelaxmi Hegde

Yep.
Thank you☺️

Thread Thread
 
pgradot profile image
Pierre Gradot

You're welcome :)