Domanda

Consider the following code:

int main (void) {
    int i = xyzzy();
    return i;
}
int xyzzy (void) {
    return 42;
}

Now, although the prototype for xyyzy is unkown at the point of use, this works in c89 mode because the default return type of a function that has no prototype is int so the implicit function prototype and actual function are compatible.

And, in fact, if you change the return type of the function to float, you get (as expected):

testprog.c:6: error: conflicting types for 'xyzzy'
testprog.c:2: error: previous implicit declaration of 'xyzzy' was here

because the implicit prototype and actual function no longer match.

The original code compiled with gcc --std=c89 --pedantic -Wall -Wextra only gives me the warning:

testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'

which is expected, because c89 has this to say in 3.7.1 Function definitions:

extern int max(int a, int b) { ... }: Here extern is the storage-class specifier and int is the type specifier (each of which may be omitted as those are the defaults).

and in 3.3.2.2 Function calls:

If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration extern int identifier(); appeared.

So the use of a function before declaring it definitely results in the default prototype being created.


However, both those phrases have been removed in c99 and we instead find in 6.5.2.2 Function calls (my bold):

If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void.

I understand it to mean that, if there's no declaration in view when you try to call a function, it's implicitly declared with a void return type.

Yet, when compiling with gcc --std=c99 --pedantic -Wall -Wextra, I get just the same warning about the implicit declaration.

Shouldn't c99 have declared that function implicitly as returning void? If it had, I would have expected a previous implicit declaration error similar to the one I got when I tried to redeclare it as returning float.

Is gcc broken here, or am I missing something in the standard?

È stato utile?

Soluzione 2

This is covered in a note to 6.5.1 Primary expressions:

2 - An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator). 79)


79) Thus, an undeclared identifier is a violation of the syntax.

A conforming implementation is required by 5.1.1.3 Diagnostics to produce a diagnostic message in response to the syntax violation of a function call expression involving an undeclared identifier as the expression denoting the called function. It is of course free to proceed to compile the program as if the identifier had been declared in the implicit-int C89 style.

The paragraph 6.5.2.2p5 must be read with reference to the constraint 6.5.2.2p1:

1 - The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.

So, if the "expression that denotes the called function" does not have type "pointer to function returning an object type", it must ipso facto (by the constraint 6.5.2.2p1) have type "pointer to function returning void", and it is this case which the "Otherwise" in 6.5.2.2p5 covers. That is, with my insertion in [square brackets]:

5 - If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, [i.e. if the expression that denotes the called function has type pointer to function returning void,] the function call has type void.

This is a case of special language being required for void as opposed to object types; is not a licence for the called function expression to be or contain an undeclared identifier.

Altri suggerimenti

You are reading the standard incorrectly. There's no such thing as implicit function declaration in C. It is removed from the language by C99.

GCC issues a warning when it sees an erroneous construct that looks like an implicit function declaration. This is OK as far as the standard is concerned. The standard requires a diagnostic here, and a warning is a diagnostic. You may use -Werror=implicit-function-declaration flag to GCC to turn this into an error.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top