cfunctiondeclaration

Multiple forward declarations inside a function


Why is the following code allowed by C99:

int main (void)
{
    int add (int, int);
    int add (int, int);

    return 0;
}

I thought tentative definitions concern global variables only (variables with file scope). This indicates that those forward declarations are not treated like variable declarations.

It does not yield any error or warnings with GCC -Wall -Wextra -Werror=shadow -std=c99 which means it is most likely either compliant with the standard (for some odd probably historic reason) or as an language extension of some sort. Is it required by the standard, what is its purpose?

I am hoping to understand function declarations and definitions within block scope completely, so that certain error/warning messages make sense.


Solution

  • Why is the following code allowed by C99:

    int add (int, int); is only a declaration; it says “There is a function named add, which external linkage, that takes two int parameters and has an int return type.”

    Repeating this declaration does not conflict with the prior declaration—if you say a thing twice, there is no conflict. C allows it largely because repeated declarations may easily occur when headers include other headers, so it is easier to allow repetitions than to require multiple programmers to coordinate their headers so that no repetition occurs.

    If a declaration were a definition that creates an object or a function, there could be problems since then you have multiple instances of a thing. So there are more involved rules for definitions. But simple declarations generally can be repeated.

    I thought tentative definitions concern global variables only (variables with file scope).

    A tentative definition is for objects only. C 1999 and C 2018 6.9.2 2 say:

    A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition

    So tentative definitions are not relevant to the code in this question.