What is C local function declaration mechanism?

2020-04-11 06:21发布

问题:

Local function declaration seems to be permitted in gcc, and I found a discussion on this: Is there any use for local function declarations?

However, my question is: is it allowed by ISO C standard? If it is, how to explain the following phenomenon which makes it puzzling:

int main(void) {
    int f(void);
    f();
}
void g(void) {
    /* g has no idea about f. It seems that the decl is limited within its
     * scope */
    f(); 
}
int f(void) {}

while

int main(void) {
    int f(void);
    f();
}
void f(void); /* error because disagreement with the local declaration (local
             declaration goes beyound its scope?) */
void f(void) { /* definition here */ }

According to the C99 standard: function names are in the same naming category. So we shall discuss the scoping mechanism to explain this. But how?

Actually, I'm working on a compiler course project which requires us to implement a simplified version of C compiler. I was trying to deal with this case but got confused.

EDIT: I know it's a common knowledge that C is procedure-oriented and requires function names to be unique. But this local style of declaration stirs clear situation, and it's hard for me to understand its principle/rule.

回答1:

Both ISO C and C++ permit local function declarations. In each case the scope of the function declaration ends at the end of the local scope. However, the function declaration and its definition have external linkage so they still need to be acceptable to the linker.

In your sample:

int main(void) {
 int f(void);
 f();
}
void f(void);
void f(void) {  }

This code compiles without error, as either C or C++. In C is should link (usually), but in C++ it will not (because of "typesafe linkage"). There will be an unresolved external for int f(void);.

[If this does not answer your question because of difficulties with your English, please clarify and I'll edit the answer.]


The C standard contains the following. n1570/S6.7.1/7:

The declaration of an identifier for a function that has block scope shall have no explicit storage-class specifier other than extern.

Clearly local function declarations are explicitly permitted.


n1570 S6.2.2/5 on external linkage:

If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

So local function declarations have external linkage. This is obvious: if they had internal or no linkage, they could not link to anything.



回答2:

To fix the second example you need to declare f in main with proper return type

int main(void) {
    void f(void);  // function declaration
    f(); // calling function
}  // scope of f ends here

void f(void) {} 

This way you inform compiler what to look for, and later it finds it indeed. Hope it helps.



回答3:

Local extern declarations indeed work just like ones outside the function except with limited scope, or alternately just like local static declarations except that the entity is externally accessible by linkage.

Why? Well, why not? It's just an extrapolation of the general rules for declarations and the extern specifier into a specific context.

I can't recall ever (purposely) using a local extern function declaration, but a few times I've hacked in a debugging variable using a local extern variable declaration. The extern declaration can be placed in some highly nested code and pass data to a debug printer in another TU.