1

関数での前方宣言の使用に問題があります。extern通常、グローバルスコープでは、キーワードを使用して宣言された未定義変数のアドレスを使用できます。簡単な例を見てください。

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};    

しかし、関数定義中にこのコードをどのように使用できますか? このように使ってみることができます。

void F (){
    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}; 
}

しかし、ここでエラーが発生しました — error C2086: 'ChIdRec Evn' : redefinition. の最初の宣言を削除できますEvnが、別のエラーが発生します — error C2065: 'Evn' : undeclared identifier.

このビットの問題を解決するにはどうすればよいですか?

4

3 に答える 3

1

関数内で型の定義を繰り返さないでください。特に、typedefグローバルなものと同じ名前と意味を持っていても、これは新しい識別子になります。

于 2012-12-11T15:32:57.760 に答える
0

extern変数がリンカーによって解決される別のコード単位で定義されていることを意味します。構造体がローカル関数で定義されている場合、それがどのように期待できるかわかりませんextern

問題は、外部変数があり、同じ変数をローカルとして宣言しようとしていることです。コンパイラは、「決心してください。それは外部ですか、それともローカルですか?」と言っています。

前方宣言の唯一の理由は{ }、構造体で初期化構文を使用できるようにすることです。ハックを使用するよりも、メンバーごとに割り当てる方が適切です。

必要に応じて を使用することもできますがvoid *、それには不注意のためのトラップが散りばめられています。

于 2012-12-11T15:40:28.980 に答える
0

extern ChIdRec Evn;関数内に配置されたときに、あなたが思っていることをしません。

グローバル変数でexternある変数。関数内で宣言しても。これによりextern、アクセスする場所のすぐ近くで、関数本体の途中でグローバル変数を使用していると言えます。ただし、ローカル変数を「前方宣言」できないことを意味します。

理論的には、struct構築せずに 1 つの場所で作成し、さらに作業を行ってからnew、C++11 の統一された初期化構文を使用してその場で作成することができます。

すなわち:

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

またはそのようなもの。(配置の使用に注意してください。フリーストア(別名ヒープ)にメモリを作成していません。また、PODでない場合new、の二重構築は危険であることに注意してください-ChIdRecにが含まれている場合、上記がリークまたはリークすることが予想されますたとえば、クラッシュします。ChIdRecstd::string

少しばかげているが正しい方法:

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

これは、非常に安全で扱いにくいものにするために、派手なものでドレスアップすることができます. 基本的に、遅延構築の抽象化により、これは少しばかげたものになります。

于 2012-12-11T15:49:36.053 に答える