2012-12-11 2 views
1

J'ai un problème avec l'utilisation des déclarations directes dans les fonctions. Habituellement, dans une portée globale, nous pouvons utiliser l'adresse de variable indéfinie qui a déclaré en utilisant le mot-clé extern. Regardez l'exemple simple.Déclarations directes dans les fonctions

typedef struct Id { 
    int a; 
} xIdRec; 

typedef xIdRec* IdN; 

typedef struct ChId{ 
    int a; 
    IdN* b; 
} ChIdRec; 

extern ChIdRec Evn; 
IdN Arr[] = {(IdN)&Evn}; 
ChIdRec Evn = {8, Arr};  

Mais comment puis-je utiliser ce code pendant la définition de la fonction? Nous pouvons essayer de l'utiliser comme ça. Nous avons maintenant une erreur - error C2086: 'ChIdRec Evn' : redefinition. Nous pouvons supprimer la première déclaration de Evn, mais nous aurons une autre erreur - error C2065: 'Evn' : undeclared identifier.

Comment puis-je résoudre ce problème de bit?

+2

ummm .. le déplacer en dehors de la fonction? –

+0

'struct ChIdRec' est une structure locale, comment peut-elle être instanciée en dehors de la fonction' F() '? – mark

+0

Pourquoi déclarez-vous de nouveau 'extern ChIdRec Evn' localement? 'extern foo bar' ne devrait se produire qu'une seule fois, c'est-à-dire dans l'en-tête du module (le cas échéant) qui implémente' foo bar'. – alk

Répondre

1

Ne répétez pas la définition des types à l'intérieur de la fonction. En particulier le typedef fait qu'il s'agit d'un nouvel identifiant même s'il a le même nom et la même signification que le global.

+0

Je pense que vous pensez que les deux blocs de code sont supposés être compilés les uns après les autres? – Yakk

+0

Je pense que l'erreur du PO montre que c'est exactement ce qui se passait. – Useless

0

extern signifie que la variable est définie dans une autre unité de code à résoudre par le lieur. Si la structure est définie dans une fonction locale, je ne vois pas comment vous pouvez vous attendre à ce qu'elle soit également extern.

Le problème est que vous avez une variable externe, puis vous essayez de déclarer la même variable que locale. Le compilateur dit "décidez-vous, est-ce externe ou local?".

Il semble que la seule raison de votre déclaration forward est que vous puissiez utiliser la syntaxe d'initialisation { } sur la structure. Mieux vaut assigner membre par membre que d'utiliser un hack.

Si vous devez alors vous pouvez utiliser void *, mais cela est saupoudré de pièges pour les imprudents.

0

extern ChIdRec Evn; ne fait pas ce que vous pensez qu'il fait lorsqu'il est placé dans une fonction. La variable extern est une variable globale. Même si vous le déclarez dans une fonction. Cela vous permet de dire que vous utilisez une variable globale extern à mi-chemin d'un corps de fonction, juste à côté de l'endroit où vous y accédez. Mais cela signifie que vous ne pouvez pas "transmettre" une variable locale.

Maintenant, en théorie, vous pouvez créer votre struct à un endroit sans le construire, faire un peu plus de travail, puis mettre en place new avec la syntaxe d'initialisation uniforme dans C++ 11.

-à-dire:

ChIdRec Evn; 
IdN Arr[] = {(IdN)&Evn}; 
new(&Evn)ChIdRec{8, Arr}; 

ou quelque chose comme ça. (Notez l'utilisation du placement new, je ne crée pas de mémoire sur le magasin libre.) Notez également que la double construction de est dangereuse si elle n'est pas POD - si ChIdRec contenait un std::string, je m'attendrais à ce que ci-dessus à fuir ou accident, par exemple

Un peu plus ridicule, mais bon, la méthode:.

unsigned char EvnBuff[sizeof(ChIdRec)]; 
IdN Arr[] = {reinterpret_cast<IdN>(&EvnBuff[0])}; 
new(&EvnBuff[0])ChIdRec{8, Arr}; 
ChIdRec& Evn = *reinterpret_cast<ChIdRec*>(&EvnBuff[0]); 
// ... code goes here 
Evn->~ChIdRec(); // before leaving body of function, iff ChIdRec::~ChIdRec exists 

qui pourrait être habillé dans des choses extravagantes pour le rendre exception sûre et moins gênant.Fondamentalement, une abstraction de construction retardée rendrait cela marginalement moins ridicule.

Questions connexes