2

I'm new to c++ and I am confused by the idea of passing a pointer array into a function.

Here's the function

void func(int *a){ a[0]=999;}

which is used by the main

int main()
{
    int a[5]={1,2,3,4,5};
    func(a);
    std::cout << a[0]<< std::endl;
}

I understand this works perfectly as the name of an array is just the address of its first element. Based on my understanding, &a refers to the address of the entire array while a refers to the address of the first element of the array, which should be identical to &a. However, if I use

int main(){
    int a[5]={1,2,3,4,5};
    func(&a);
    cout<< a[0]<< endl;
}

It returns the compiler error: no known conversion from 'int (*)[10]' to 'int *' for 1st argument; remove &

Could anyone please explain what's going on here?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 2
    This is because even though their value is the same their type is different. In particular, `a` decays to `int*` while `&a` is an `int (*)[5]`. – Jason May 27 '22 at 14:04
  • [What is array to pointer decay?](https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay) Read that and prepare to adjust some of your assumptions. An array is _not_ a pointer to the first element, but it can _decay_ to one under many circumstances, such as when you try to pass an array to a function. – Drew Dormann May 27 '22 at 14:05
  • You can use `a` (which does pointer decay; very common practice in C and C++) or `&a[0]`. – Eljay May 27 '22 at 14:05
  • Side note: Be cautious. If the name of an array was just an address, the `sizeof` operator would just return the size of an address, not the size of the array. That's not true, so the name of the array represents a bit more than just the address. – user4581301 May 27 '22 at 14:08
  • 1
    If `a` is the address of the first element, then `&a` is the address of the address of the first element. That's one address too many. This may be a bit easier to understand without by using a version of the array that has already decayed: `int* firstElement = a; int** pointer = &firstElement;` the result is a pointer to a pointer, not a pointer. – fabian May 27 '22 at 14:16
  • In addition to preceding comments - Since minor errors can mislead people who try to help you into addressing the wrong problem, getting things as accurate as possible in the question is important. Your error message is not consistent with the code you provided in the question. `a` is an array of five `int`, and `&a` is of type "pointer to array of five `int`" (or `int (*)[5]`). There is no way your code would give an error referring to an `int (*)[10]` (a pointer to an array of ten `int`) since there is no array with ten elements anywhere. – Peter May 27 '22 at 14:19

3 Answers3

3

Case 1

I understand this works perfectly as the name of an array is just the address of its first element.

The above statement is not technically correct. The first example worked because in many contexts(including when passing an array as an argument by value to a function) the array decays to a pointer to its first element due to type decay. This means, in example 1, when you passed a as an argument, there was an implicit array-to-pointer conversion which converted your array a of type int[5] to a pointer to its first element which is the type int*. Thus in example 1, the type of the argument and the type of the parameter matches and example 1 succeeded.

Note also that even though the decayed pointer and the address of the array both have the same value their types are different. The decayed pointer is of type int* while the &a is of type int (*)[5].

Case 2

Could anyone please explain what's going on here?

This is because a is of type int [5] which means &a is of type int (*)[5] which doesn't match with the type of the parameter int*.

That is, when you modified your code, you were passing &a which is of type int (*)[5] but the function parameter is of type int* and hence there is a mismatch in the type of the parameter and the argument you're passing and as there is no implicit conversion from a int (*)[5] to an int* we get the mentioned error saying:

no known conversion from 'int (*)[5]' to 'int *'
Jason
  • 36,170
  • 5
  • 26
  • 60
3

I understand this works perfectly as the name of an array is just the address of its first element.

This is a subtly wrong understanding. The array int[10] can implicitly convert to a pointer to (address of) the first element int*. This implicit conversion happens when you call the function that accepts int* parameter and passing int[10] argument.

&a refers to the address of the entire array while a refers to the address of the first element of the array, which should be identical to &a

The value of the pointers is identical. But the type of the pointers is different. One is a pointer to an array int (*)[10] and the other is a pointer to an element of such array int*. Neither type implicitly converts to the other, and hence you cannot pass &a as an argument to the function that expects int*. The type system of the language prevents you from making a mistake. This is explained by the compiler diagnostic message.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

See a as a pointer. It points to the first element of the array, a[0] (or *a).

Then &a is the address of the pointer, which is unrelated to the above.

Note that (&a)[0] or *(&a) return the pointer, while (&a)[0][0] or (*(&a))[0] or *((&a)[0]) or **(&a) return the first element of the array.