tags:

views:

147

answers:

2

Hello, I noticed a very curious behavior that, if standard, I would be very happy to exploit (what I'd like to do with it is fairly complex to explain and irrelevant to the question).

The behavior is:

static void name();
void name() {
    /* This function is now static, even if in the declaration
     * there is no static keyword. Tested on GCC and VS. */
}

What's curious is that the inverse produces a compile time error:

void name();
static void name() {
    /* Illegal */
}

So, is this standard and can I expect other compilers to behave the same way? Thanks!

+11  A: 

C++ standard:

7.1.1/6: "A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration" [or unless it's const].

In your first case, name is declared in a namespace scope (specifically, the global namespace). The first declaration therefore alters the linkage of the second declaration.

The inverse is banned because:

7.1.1/7: "The linkages implied by successive declarations for a given entity shall agree".

So, in your second example, the first declaration has external linkage (by 7.1.1/6), and the second has internal linkage (explicitly), and these do not agree.

You also ask about C, and I imagine it's the same sort of thing. But I have the C++ book right here, whereas you're as capable of looking in a draft C standard online as I am ;-)

Steve Jessop
I'm using C++, but I added a C tag because I figured it would be the same in C.
Andreas Bonini
oh and thanks for the great answer
Andreas Bonini
+2  A: 

Qualifiers that you put on the function prototype (or that are implied) are automatically used when the function is declared.

So in your second case the lack of static on the prototype meant that the function was defined as NOT static, and then when it was later declared as static, that was an error.

If you were to leave off the return type in the prototype, then the default would be int and then you would get an error again with the void return type. The same thing happens with __crtapi and __stdcall and __declspec() (in the Microsoft C compiler).

John Knoeller