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.

6
  • That's not a reference, that's the "address-of" operator. Commented Aug 17, 2014 at 18:18
  • Also, &studentAge is a pointer to an array of 5 integers. studentAge is an array so this makes sense. Commented Aug 17, 2014 at 18:19
  • 1
    Also, &x[i] is equivalent to &(x[i]), not (&x)[i]. Commented Aug 17, 2014 at 18:19
  • Related. Commented Aug 17, 2014 at 18:23
  • Oli, aren't the terms reference operator and address-of operator interchangeable? Commented Aug 17, 2014 at 18:25

3 Answers 3

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 *

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! That makes perfect sense.
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.

2 Comments

Thank you for the clarification. In that case, how is & an exception to array->pointer decay?
It is an exception, but only when applied to an array. In this context, you're applying it to something that's not an array.
-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

1 Comment

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.