Home > other >  Understanding relationship between arrays and pointers
Understanding relationship between arrays and pointers

Time:03-29

I was recently reading about difference between T* and T[size], T being the type, and it make me curious so I was playing around with it.

int main()
{
    int a[10];
    using int10arrayPtr_t = int(*)[10];
    int10arrayPtr_t acopy = a;
}

In the above code, int10array_t acopy = a; is an error with message

error C2440: 'initializing': 
cannot convert from 'int [10]' to 'int10array_t'

And this compiles:

int main()
{
    int a[10];
    using int10arrayPtr_t = int*;
    int10arrayPtr_t acopy = a;
}

Isnt the type int(*)[10] closer the the type of int a[10]; than int*? So why does it not allow the first case?

CodePudding user response:

You need to take the address explicitly, e.g.

int10arrayPtr_t acopy = &a; // acopy is a pointer to array containing 10 ints
//                      ^

The 2nd case works because array could decay to pointer, for a, it could convert to int* implicitly, and acopy is a pointer to int (note that it's not a pointer to array).

CodePudding user response:

Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.

So if you have for example an array

T a[N];

then you may write

T *p = a;

because due to the implicit conversion the above declaration is equivalent to

T *p = &a[0];

If you apply the address of operator & to an array then you get a pointer dereferencing which you will get the original object.

For example

T a[N];
T ( *p )[N] = &a;

std::cout << sizeof( *p )  << '\n';

the output statement will give the size of the array a.

Here is a demonstration program.

#include <iostream>
#include <iomanip>
#include <type_traits>

int main()
{
    const size_t N = 10;
    using T = int;

    T a[N];

    T *p = a;

    std::cout << "std::is_same_v<T &, decltype( *p )> is "
        << std::boolalpha << std::is_same_v<T &, decltype( *p )>
        << '\n';

    std::cout << "sizeof( *p ) = " << sizeof( *p ) << '\n';

    T( *q )[N] = &a;

    std::cout << "std::is_same_v<T ( & )[N], decltype( *q )> is "
        << std::boolalpha << std::is_same_v<T ( & )[N], decltype( *q )>
        << '\n';

    std::cout << "sizeof( *q ) = " << sizeof( *q ) << '\n';
}

The program output is

std::is_same_v<T &, decltype( *p )> is true
sizeof( *p ) = 4
std::is_same_v<T ( & )[N], decltype( *q )> is true
sizeof( *q ) = 40

CodePudding user response:

In your first example, the symbol int10arrayPtr_t is an alias for a "pointer to an array of 10 integers". In your second example the same symbol is an alias for "pointer to a single integer". That's quite a different thing.

Also, it's true that arrays decays to pointers to their first element, but it's a pointer to a single element of the array. I.e. plain a will decay to &a[0], which have the type int*. To get a pointer to the array you need to use the pointer-to operator & for the whole array, as in &a.

  • Related