Search code examples
c++arrayspointersimplicit-conversion

Understanding relationship between arrays and pointers


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?


Solution

  • 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