1

I'm trying to figure out exactly how the relationship works between arrays and pointers in C++. I have read a number of threads and I feel as if it's just not sticking. Looking at this short bit of code here:

int studentAge[5];
int *p = &studentAge[0];

I've read that the reference operator(&) creates an exception to the array->pointer decay rule. So, from what I've read I believe they're saying that &studentAge is technically a pointer to 5 integer values, not a pointer to a single integer. To elaborate more, is it right to say that its type will be int(*)[5], which cannot convert to int*?

If it's a pointer to 5 integer values, then wouldn't that mean that it did, in fact, decay to a pointer? Or am I completely wrong in thinking this?

Furthermore, with this line of code:

p = studentAge;

Without the reference operator does the studentAge array now decay to a pointer? I apologize if I'm all over the place with this, but as I stated before, I'm having a difficult time getting 100% clear on this.

David G
  • 94,763
  • 41
  • 167
  • 253

3 Answers3

3

If you take an array argument to a function, it will indeed decay to a pointer. If you take a reference to an array, it will not.

#include <iostream>

void take_array(int arr[]) { // same as (int *arr)
    // prints sizeof int*
    std::cout << "take_array: " << sizeof arr << '\n';
    ++arr; // this works, you can increment a pointer
}


void take_array_ref(int (&arr)[10]) { // a reference to an array of int[10]
    // prints (sizeof int) * 10
    std::cout << "take_array_ref: " << sizeof arr << '\n';
    //++arr; // this fails to compile. you can't increment an array
}

int main() {
    int arr[10]; // sizeof arr == (sizeof int) * 10
    take_array(arr); // decays
    take_array_ref(arr); // doesn't decay

    int arr2[2];
    take_array(arr2);  // compiles because it decays
    //take_array_ref(arr2); // doesn't compile, type mismatch 
}

note that the first signature could also be void take_array(int arr[1000]); or any other value, it would still be the same as having a pointer; the output would still be the same, the arr parameter would still effectively be int *

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
2

Firstly, &studentAge[0] means &(studentAge[0]).

In the context of studentAge[0], the array indeed decays to a pointer to the first element, i.e. of type int *. This is then immediately dereferenced by the [0], leaving a type of int. You then finally take the address of that (with the address-of operator &), getting you back to an int *.

In short, p = &studentAge[0] is identical to p = studentAge.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
-2

One important thing to note is when we define an array, the compiler allocates a contiguous block of memory. Another important thing to note, that arrays are treated as pointers (references) in C/C++ So when we create any array say:

int studentAge[5] = {1,2,3,4,5};

It allocates this array as a continuous memory block.

"studentAge" is basically an (int *) pointing to the start of the array

Therefore, the below 2 statements are basically doing the same thing

int *p = & (studentAge[0]);
int *p = studentAge;

Now to check if they are contiguous we can do the following:

std::cout << *p << std::endl; // prints 1
std::cout << *(p+1) << std::endl; // prints 2
std::cout << *(p+2) << std::endl; // prints 3
std::cout << *(p+3) << std::endl; // prints 4
std::cout << *(p+4) << std::endl; // prints 5
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
Raghav
  • 11
  • 3
  • `studentAge` isn't "basically an `(int*)`". It *decays* into an `int*` as necessary, but it's **not** an `int*`. If it were, `sizeof(studentAge)` would return `sizeof(int*)` and it doesn.t – Nik Bougalis Aug 17 '14 at 19:25