문제

The related C program is below:

    #include <stdio.h>

    void testifbarisvisible();

    int main()
    {
            void bar(int);
        bar(1);
        testifbarisvisible();
    }

    void testifbarisvisible()
    {
        bar(2);
    }

    void bar(int x)
    {
        printf("functionbar\n");
    }

The output of gcc is:

% gcc -std=c99 -c /tmp/notfilescope.c
/tmp/notfilescope.c: In function ‘testifbarisvisible’:
/tmp/notfilescope.c:14:2: warning: implicit declaration of function ‘bar’
/tmp/notfilescope.c:7:7: note: previous declaration of ‘bar’ was here
/tmp/notfilescope.c:14:2: error: incompatible implicit declaration of function ‘bar’
/tmp/notfilescope.c:7:7: note: previous implicit declaration of ‘bar’ was here

After I removed the statement in line 7, the output is:

% gcc -std=c99 -c /tmp/notfilescope.c
/tmp/notfilescope.c: In function ‘main’:
/tmp/notfilescope.c:8:2: warning: implicit declaration of function ‘bar’
/tmp/notfilescope.c: At top level:
/tmp/notfilescope.c:17:6: warning: conflicting types for ‘bar’
/tmp/notfilescope.c:8:2: note: previous implicit declaration of ‘bar’ was here

The version of gcc is:

% gcc --version
gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE

I'm confused about the difference between the two outputs of gcc.

This is from the gcc's documents, "Declarations of external variables and functions within a block apply only to the block containing the declaration.In other words, they have the same scope as any other declaration in the same place."

So I think that the function declaration in line 7 has no relationship with the function call in line 14. But the result indicate that opinion was wrong. They are all implicit declaration of function 'bar', but one of them leads to error (incompatible implicit declaration of function ‘bar’), and the other one leads to warning (conflicting types for ‘bar’), why?

This question has confused me a long time. Can someone help me?

도움이 되었습니까?

해결책

Within main, bar has only function scope; it is known only within main. However, C has another process called linkage. Per C 1999 6.2.2 1, “An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage.”

In main, the declaration void bar(int); declares bar with external linkage, per C 1999 6.2.2 5: “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.”

Then, in testifbarisvisible, bar is not in scope. The statement bar(2); implicitly declares bar to be external, and, because bar is not in scope, it is an implicit declaration of bar with no prototype. This implicit declaration has a different type than the previous void bar(int);, but, because of linkage, it must refer to the same function. (Per 6.2.2 2, “In... an entire program, each declaration of a particular identifier with external linkage denotes the same object or function.”) This is a conflict, so the compiler produces an error.

When you remove void bar(int);, there is no explicit declaration of bar in main. Instead, bar is implicitly declaration by the following line, bar(1);. This implicit has the same type as the implicit declaration in testifbarisvisible. Because the declarations are identical, there is no error. The compiler still gives you a warning because implicit declarations are dangerous (because the eventual explicit declaration might be in a different file and might be different, which can cause undiagnosed errors at execution).

다른 팁

I'd say the result you get is reasonable.

As soon as you write

void bar(int);

you are declaring that there is a function with that signature somewhere in this compilation unit and this is not an implicit declaration, it is explicit, if anything. But, as the documentation notes, this declaration does not escape the scope it is in, so when you get to

void testifbarisvisible()
{
    bar(2);
}

no such declaration is in scope, and the compiler complains.

The problem of you code is that when you declare a function prototype inside another function this mean that you want to call it only from this function (the function is not visible outside).

In our case bar function is only visible inside main, not in the function testifbarisvisible, to make it visible to all your program the declaration must be done outside (like the way you declare global vars) or in a header file.

#include <stdio.h>

void testifbarisvisible();

int main()
{
    void bar(int);  // bar can be use inside main, not outside
    bar(1);
    testifbarisvisible();
}

void testifbarisvisible()
{
    // void bar(int); // If you want to use it inside testifbarisvisible
    bar(2);
}

void bar(int x)
{
    printf("functionbar\n");
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top