1

私は次のようなものをコンパイルしようとしました:

struct A
{   int a;
    struct B
    {    int c;
    };
};

このコードをコンパイルすると、コンパイラから次のような警告メッセージが表示されます。

declaration does not declare anything [enabled by default]

のインスタンスを定義していないことはわかっていますstruct B。これは、 variable にアクセスできないことを意味しますc。それでもコンパイラはこのコードを警告付きでコンパイルします。全体のポイントは何ですか?代わりにコンパイラがコンパイル エラーを出さないのはなぜですか?

追加情報:
のサイズは、私のマシンstruct Aの のサイズと同じですint!!

4

4 に答える 4

4

これを行うことができるため:

struct A
{   int a;
    struct B
    {    int c;
    };
};

int main()
{
    struct A a = {1};
    struct B b = {2};

    return a.a + b.c;
}

ノート:

  • を宣言した後にセミコロンが必要ですがB、これはコードにありません
  • これは特に有用ではありませんが、記録的な目的 (つまり、タイプ間の関係またはグループ化を示唆する) には役立つと思います。
  • C++ では、2 番目の変数の型はA::Bになりますが、C には同じスコープ規則がありません (すべての構造体は、事実上、グローバル構造体名前空間に属しているだけです)。

許可した動機については…

struct Outer {
    struct {
        int b;
    } anon;
    /* this ^ anonymous struct can only be declared inside Outer,
       because there's no type name to declare anon with */

    struct Inner {
        int c;
    } named;
    /* this ^ struct could be declared outside, but why force it to be
       different than the anonymous one? */

    struct Related {
        double d;
    };
    /* oh no we have no member declared immediately ... should we force this
       declaration to be outside Outer now? */

    struct Inner * (*function_pointer)(struct Related *);
    /* no member but we are using it, now can it come back inside? */

    struct Related excuse;
    /* how about now? */
};

このようにネストされた型宣言を許可したら、その型のメンバーがすぐに存在することを要求する特定の動機があるとは思えません。

于 2012-12-08T18:10:17.620 に答える
3

通常、警告は、コードが意図したとおりに動作しない可能性が高いが、その言語では合法であることを意味します。コンパイラは、「これはおそらくあなたが本当にやりたかったことではありませんが、言語が許可していると言っているので、許可しなければなりません」と言っています。C標準で許可されているため、コンパイラはこのコードのエラーを表示できません。したがって、許可する必要があります(GCCの-Werrorオプションを使用して警告をエラーに変えるなど、そのようなエラーを具体的に要求しない限り)。

C 標準は、プログラムで意味のあるすべてを定義しようとはしません。たとえば、次のことは C では合法です。

3;
if (x) then foo(); else foo();
x = 4*0;

最初のステートメントには副作用がなく、その戻り値は使用されません。ただし、ステートメントは単なる式である可能性があるため、C では合法です。2 番目のステートメントは を呼び出すだけなfoo()ので、ifは無意味です。3 番目のステートメントでは、4 を掛けても意味がありません。

意味のないものをすべて禁止する C 標準を作成するのは非常に困難です。そして、それは確かに努力する価値はありません。これはあなたの回答の一部です: C 標準を作成する委員会が言語を構築するとき、彼らは意味をなさないものを除外するために技術仕様を書き直すことに多くの時間を費やしたいですか? 重大なバグを引き起こす可能性のあるものを避けることが価値があると思われる場合は、そうです。しかし、多くの場合、時間の価値がなく、仕様が不必要に複雑になります。

ただし、コンパイラはこれらのいくつかを認識して警告することができます。これにより、多くのタイプミスやその他の間違いを見つけることができます。

一方、これらの構造は、異常な状況から生じることがあります。たとえば、プログラムにはstruct A、さまざまなターゲットやさまざまな機能をビルドするときにさまざまな方法で定義するプリプロセッサ ステートメントが含まれている場合があります。これらのターゲットの一部では、 でstruct Bメンバーが必要ないため宣言されていない可能性がありますが、プリプロセッサ ステートメントをそのように記述する方が簡単だったという理由だけで、(オブジェクトではなく型)struct Aの宣言は存在したままです。struct B

したがって、コンパイラーは、さまざまなプログラムを作成するプログラマーの邪魔にならないように、これらのことを許可する必要があります。

于 2012-12-08T19:05:23.267 に答える
3

次のことを行うのは合法です (ただし、非常に悪いスタイルです)。

struct A {   
    int a;
    struct B {    
        int c;
    };
};
struct B B_instance;
struct A A_instance;

また、コンパイラは、構造体型を使用する後の変数について認識していないため、エラーになることはありません。

于 2012-12-08T18:10:11.100 に答える
1

実際、struct Bここで宣言していますが、その型の変数を宣言していません。

これは警告ですが、修正する必要があります。おそらくあなたは次のことを意味しました:

struct A
{   int a;
    struct B
    {
        int c;
    } c;
};
于 2012-12-08T18:06:41.120 に答える