So while it is common/typical to accept an array that has decayed to a pointer like the following
#include <iostream>
void example(int* data)
{
std::cout << data[0] << ' ' << data[1] << ' ' << data[2] << std::endl;
}
int main()
{
int data[3] = {1, 2, 3};
example(data);
}
I noticed that you can also seemingly do the opposite. Namely you can pass a pointer that will undecay(?) back to an array
#include <iostream>
void example(int data[3])
{
std::cout << data[0] << ' ' << data[1] << ' ' << data[2] << std::endl;
}
int main()
{
int data[3] = {1, 2, 3};
example(data);
example(nullptr); // Is this legal? Can I prevent this?
}
Note that the data
argument of example
has changed from int*
to int[3]
yet I am still able to pass nullptr
. Changing the argument to std::array<int, 3>
will obviously prevent this, but I'm curious if this implicit conversion is described by the standard? There is a lot of commentary on "array to pointer" implicit conversion, but this seems to be the other way around.
In fact,
void example(int data[3])
is
void example(int data[])
or
void example(int* data)
You need
void example(/*const*/ int (&data)[3])
to have array reference, (and so rejecting pointer or array of different size).
When you have
void example(int data[3])
that array itself decays to a pointer so the function is actually
void example(int* data)
which is why you can still pass nullptr
to the function. The relevant paragraph for this is [dcl.fct]/5
The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own parameter-declaration ([dcl.decl]). After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”. [...]
emphasis mine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With