2009-12-22 10 views
6

J'ai remarqué un comportement très curieux que, si standard, je serais très heureux d'exploiter (ce que j'aimerais en faire est assez complexe à expliquer et non pertinent à la question).Déclarer une fonction statique et postérieure non statique: est-elle standard?

Le comportement est:

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. */ 
} 

Ce qui est curieux est que l'inverse produit une erreur de compilation:

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

Alors, est-ce standard et puis-je attendre d'autres compilateurs à se comporter de la même manière ? Merci!

Répondre

12

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].

Dans votre premier cas, name est déclaré dans un champ d'espace de noms (en particulier, l'espace de noms global). La première déclaration modifie donc le lien de la deuxième déclaration.

L'inverse est interdit parce que:

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

Ainsi, dans votre deuxième exemple, la première déclaration a une liaison externe (par 7.1.1/6), et le second a une liaison interne (explicitement), et ceux-ci ne sont pas d'accord.

Vous posez aussi des questions sur C, et j'imagine que c'est le même genre de chose. Mais j'ai le livre C++ ici, alors que vous êtes aussi capable de regarder un projet de norme C en ligne que moi ;-)

+0

J'utilise C++, mais j'ai ajouté un tag C parce que je pensais que ce serait le même en C. –

+0

oh et merci pour la bonne réponse –

3

Les qualificatifs que vous mettez sur le prototype de fonction (ou qui sont implicites) sont automatiquement utilisés lorsque la fonction est déclarée. Par conséquent, dans votre deuxième cas, l'absence de static sur le prototype signifiait que la fonction était définie comme NON statique, puis lorsqu'elle était déclarée comme statique, c'était une erreur.

Si vous laissez le type de retour dans le prototype, la valeur par défaut sera int, puis vous obtiendrez une erreur avec le type de retour void. La même chose se produit avec __crtapi et __stdcall et __declspec() (dans le compilateur Microsoft C).