This question builds on this one, which describes how the following are equivalent:
int f(int a[10]) { ... } // the 10 makes no difference
int f(int a[]) { ... }
int f(int *a) { ... }
In documentation about Function prototype scope, the following example is provided:
int f(int n, int a[n]); // n is in scope, refers to first param
This lead me to question to what extent the following are equivalent:
// 1.
int f(int n, int a[n]) { ... }
int f(int n, int *a) { ... }
// my guess: exactly equivalent
// 2.
int x = 10; int f(int a[x]) { ... }
int x = 10; int f(int *a) { ... }
// my guess: exactly equivalent
// 3.
int f(int a[n], int n) { ... }
int f(int *a, int n) { ... }
// my guess: not equivalent: first f won't compile, second will
Concluding question:
- provided both compile, are
int f(int arr[n])andint f(int *arr)always equivalent? - why does the compiler want to lookup identifier
n, even though its value will not be used.- my guess: the only reason to have included the
nin the source code was as documentation to indicate the minimum length the array should have. Ensuring thatnis in scope, and has correct type, ensures this documentation makes sense
- my guess: the only reason to have included the
No. The C standard is defective on this point; it does not say whether the
ninint arr[n]is evaluated or not.int arr[n]nominally declares a variable-length array (supposingnis an identifier for some object, not a macro for a constant). The C standard says that sizes of variable length arrays are evaluated, and it also says the parameter declarationint arr[n]is automatically adjusted to beint *arr, but it is not clear on which order these occur in. GCC and Clang differ on this point; Clang evaluates the array size, but GCC does not. For an unqualified objectn, this makes no difference, but, ifnis volatile or the array size is some other expression with side effects, it does make a difference.The compiler needs to parse the code to determine its grammatical structure. There are valid keywords that can appear there, such as
static,const,restrict,volatile, and_Atomic. Other keywords may be an error. Or you could have some other expression, such asn * 3. If you do haventhere and it is an identifier for anint, the compiler can ignore it. If you haventhere and it is an identifier for a function, the compiler should issue a diagnostic message. Whatever is there, the compiler needs to analyze it and either accept it or issue an appropriate diagnostic message.Array sizes in parameter declarations are more useful in multidimensional arrays, as in
void f(size_t m, size_t n, int Array[m][n]). In this, themis as above and may be omitted, but thenis used and is critical.