To understand array decay, consider the following program:

#include <iostream>
 
void print2Elemenet(const int arr[5])
{
    std::cout << arr[2] << '\n';
}
 
int main(int argc, char const *argv[])
{
    int arr[]{1, 2, 3, 4, 5};
    print2Elemenet(arr);
 
    int arr2[]{1, 2, 3, 4, 5};
    print2Elemenet(arr2);
    return 0;
}

If we compile this program, this would successfully compile and work. But how is this even possible to pass array of different length to the same function? This is happening because C-style array decay.

C-style array decay is an implicit conversion from C-style array of a type to the pointer of the same type and the pointer points to the first element of the array. This conversion happens when C-style array is used in an expressions such as function call. The pointer is assigned address of the first element of the array.

So, in the above case, for first call to print2Element(arr), arr is converted to int* and passed to the function. Compiler would interpret function parameter const int array[5] as const int*. Finally the function would be called.

When second function call is made, again same thing happens and function gets called.

When C-style arrays are decayed?

  1. When passed a function that does not accept the array by explicit reference. For example:
 
void printArray(const int (&arr)[5])
{
    std::cout << std::size(arr) << '\n';
    for (const auto &item : arr)
    {
        std::cout << item << '\n';
    }
}
 
int arr[5]{1, 2, 3, 4, 5};
printArray(arr);

In printArray(arr), arr will not get decayed as it is being passed by reference.

Apart from this, the array will decay when passed to a function. For example

void fun(const int*);
void fun(const int arry[5])
void fun(const int arry[])
  1. When initializing a pointer of the same type.
int *ptr{arr};
  1. In expressions such as arithmetic expressions
std::cout << arr + 1;

arr would be converted to int* and then incremented by 1 which gives address after 4 bytes (if int is of size 4bytes).

  1. Passing array to sizeof operator. For example:
std::cout << sizeof(arr); // does not decay

Why C-style array decay?

Decaying C-style array was made for following:

  1. So that C-style arrays of different lengths can be passed to same function as above. It was because there was no syntax to specify array of any length and no function template as C++.
  2. Avoid copying C-style array while passing to functions as there was no references as C++ does.

operator[] and decay pointer

We can access array elements by using operator[] on the decay pointer. For example:

int arr[5]{1, 2, 3, 4, 5};
 
auto ptr{arr}; // implicitly converted to pointer of type int pointing to first element of the array
 
std::cout << ptr[0] << '\n'; // gives the first element
// or
std::cout << *ptr << '\n'; // gives the first element
.
std::cout << ptr[1] << '\n'; // gives the second element

It uses pointer arithmetic and subscripting to subscript a decay pointer.

Function parameter syntax for C-style array

In print2Element(), we have used parameter as const int arr[5] would gets converted to const int *arr by the compiler, we could directly use this syntax:

void print2Elemenet(const int *arr)
{
    std::cout << arr[2] << '\n';
}

And calling it would work as usual. One more thing to notice in the syntax const int array[5], we can omit the length information as compiler does not care about the length (as length information is lost in c-style array decay). For example:

void print2Elemenet(const int arr[])
{
    std::cout << arr[2] << '\n';
}

However, we should prefer above syntax over pointer syntax because it makes the intent clear of passing an array, not any pointer, to the function.

Why we should avoid C-style arrays?

There are following problems with C-style arrays and so they should be avoided:

  1. C-style arrays are decayed when passed to a function, so function has to be array specific. We can’t use any other arrays with the function.
  2. When passed to the function, they loss on the length information and it is hard to work with length without knowing the length.

References

  1. https://www.learncpp.com/cpp-tutorial/c-style-array-decay/