简体   繁体   中英

Variable declaration in function prototype and in block code : difference?

Why int array[] raise a compilation error in main but not in function prototype ? Should it mean that it is better to always write int * array in function prototype ?

void myfoo (int array[]) { // No compilation error
;}

void myfoo1 (int *array1) { // No compilation error
;}

int main() {
    int array[]; // Compilation error
    int* array1; // No compilation error
}

In your code, inside the function, writing int array[]; for an array definition is a semantic error.

In this case, array is a variable with no linkage, ( "a block scope identifier for an object declared without the storage-class specifier extern " ) and as per the spec:

If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, [....]

An empty [] (with or without space(s) in between), does not make a valid construct for an array definition, as the size of the array remains unknown (Notice the lack of an explicit brace-enclosed list of initializer, too). Thus, your compiler complains, as the type is not complete and it has no idea of the total amount of memory to be reserved for that array variable.

On the other hand, for function parameters, an array type parameter actually decays to a pointer to the type, so, specifying the array size is not mandatory. Quoting chapter §6.7.6.3

A declaration of a parameter as ''array of type'' shall be adjusted to ''qualified pointer to type'', where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. [...]

and

If the function declarator is not part of a definition of that function, parameters may have incomplete type and may use the [*] notation in their sequences of declarator specifiers to specify variable length array types.

So, basically, a statement

 void myfoo (int array[])

is equivalent as

void myfoo (int *array)

so, this is accepted by compiler.

Fundamentally, the reason an array declaration inside the block for main needs a size and the array declaration in the function parameter does not is that the declaration in main is defining an array, whereas the function parameter is merely receiving an array that something else defines.

So the definition in main needs a size because it must reserve storage for the array.

The function parameter is merely receiving an array, so it only needs to know where the array starts. It does not need to know the size. (That is, the compiler does not need to know the size in order to compile the code. The function may need to know the size in order to perform its intended purpose, but that is a matter for the programmer, not the compiler.)

Due to C rules, arrays can never actually be passed as function arguments. Whenever an array is given as a function parameter, the compiler automatically converts it to a pointer to its first element. Similarly, a function parameter can be a pointer but cannot actually be an array. When you declare a function parameter as an array, the compiler automatically adjust it to declare a pointer instead. So the function declaration void myfoo(int array[]) is automatically adjusted to be void myfoo(int *array) .

The specific rule that requires the declaration in main to have a size is C 2018 6.7 7:

If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer;…

void myfoo (int array[]) { // No compilation error
;}

It means myfoo() will be called with an integer array (of any size). Compiler can just compile it.

void myfoo1 (int *array1) { // No compilation error
;}

It means myfoo1() will be called with a pointer to integer. Compiler can just compile it.

int main() {
    int array[]; // Compilation error
    int* array1; // No compilation error
}

int array[];

This is the definition of the array. But the compiler can not determine the size of the array. So it does not know how much memory to be allocated. So you have to provide either size or initialize it with some values as below.

int array[3];

or

int array[] = {1,2,1};

.

int* array1;

This is just a declaration of integer pointer. Nothing wrong in it and compiler can compile it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM