Search code examples
cgcccc

How does a C compiler parse code like `arr[]`?


It is well known that function declarations like

void foo (int arr[])

and

void foo (int* arr)

are identical since array variables are just pointers to the first element of the array.

My question is about how a C compiler processes the first version. Does it work just like other compiler directives (#define) and simply substitute for the second?


Solution

  • … array variables are just pointers to the first element of the array.

    They are not. There are contexts in which an array is converted to a pointer to its first element, but an array is not just a pointer to its first element, and it cannot be because there are contexts in which an array is not converted to a pointer to its first element. The compiler must distinguish between an array and a pointer until sufficient context is resolved.

    For purposes of specifying C semantics, in declarations of function parameters, a declaration of an array is automatically adjusted to be an declaration of a pointer. However, that adjustment is a conceptual act. It does not have to be implemented in a particular way in a compiler. It can be implemented in various ways, or the necessary semantics can be provided without any actual adjustment.

    For example, when a parameter is declared to be a pointer, the compiler has to do certain things such as:

    • When the function is called, the compiler must check the rules applicable to passing an argument for a pointer parameter and may need to convert the argument to the parameter type.
    • In the function definition, the compiler must process references to the parameter as references to a pointer object.

    Now, when a parameter is declared to be an array, the compiler can implement the semantics required by the C standard by fully processing the declaration and constructing its own internal representation of the declared identifier and then adjusting that internal representation to represent a pointer type. However, another way for the compiler to implement the semantics is to keep the internal representation unchanged but process it using the same rules it would for a pointer parameter:

    • When the function is called, check the rules applicable to passing an argument for a pointer parameter and, if applicable, convert the argument to the pointer type corresponding to the declared array type.
    • In the function definition, the compiler process references to the parameter as references to a pointer object.

    So, there are multiple ways a compiler can implement the behavior required by the C standard.