3

Ubuntu (i686) で gcc バージョン 4.3.3 を使用しています。私の理解不足と問題を説明するために、簡略化したテスト プログラムを作成しました。プログラムは、私が実装した構造体のサイズを教えてくれます。だから私は Message のtypedef構造とちょっと遊んでみる main を持っています:

#include <stdio.h>

typedef struct {
    int size; 
    enum {token=0x123456}; 
} Message;

int main(int argc, char * argv[])
{
    Message m;
    m.size = 30;
    printf("sizeof(int): %d\n",sizeof(int));
    printf("sizeof(0x123456): %d\n",sizeof(0x123456));
    printf("sizeof(Message): %d\n",sizeof(Message));
    printf("sizeof(m): %d\n",sizeof(m));
}

このソースを gcc でコンパイルすると、次の警告が表示されますが、これは理解できません。

$ gcc sizeof.c
sizeof.c:5: warning: declaration does not declare anything

行 5 は列挙行を参照します。作成したすべてのMessageにそのトークンが必要です。私は何を間違っていますか?その警告を取り除くために何を変更する必要がありますか?

私のメインにはsizeof()の呼び出しがいくつか含まれています。プログラムを実行すると、整数のサイズが 4、16 進数のサイズが 4 であることが出力でわかりますが、typedef 構造体メッセージのサイズも 4 です。

$ ./a.out
sizeof(int): 4
sizeof(0x123456): 4
sizeof(Message): 4
sizeof(m): 4

それは私を非常に混乱させます。Messageサイズが 4 であるのに、それぞれのサイズが 4 の整数と整数が列挙型内に含まれているのはなぜですか。

しかし、なぜ4つだけなのですか?メッセージの実際のサイズをバイト単位で取得するにはどうすればよいですか? それとも、これが本当のサイズですか?もしそうなら、なぜですか?

CとC++の間でメッセージのサイズを取得することに違いはありますか?

4

8 に答える 8

10

列挙型は実際にはスペースを必要としません。これは、コンパイラーがリテラル番号のセットを名前で認識するための単なる方法です。

于 2012-06-14T12:07:35.560 に答える
4

あなたは何も宣言していません:

enum {token=0x123456};

あなたの宣言は次のようになります。

typedef struct {
    int size; 
    int; 
} Message;

次のように構造体を宣言すると:

typedef struct {
    int size; 
    enum {token=0x123456} e; 
} Message;

2 つのフィールドがありますがe、何も初期化されません。インスタンスごとに手動で設定する必要があります: message.e=token.

目的を達成する正しい方法は、C++ でコンストラクターを使用することです。

struct Message {
    int size; 
    int token;
    Message() : token(0x123456) {}; 
};

または C++11 の非静的データ メンバー初期化子:

struct Message {
    int size; 
    int token=0x123456;
};

C の構造体宣言でフィールドを初期化する方法はありません。

于 2012-06-14T12:33:43.867 に答える
3
typedef struct {
    int size; 
    enum YouShouldDeclareAName {token=0x123456}; 
} Message;

列挙型はMessage構造体のサブクラス/サブタイプであるため、オブジェクトではなくクラスにバインドされます。名前空間のように。それを使用して変数を作成することはありません。次のように変更します。

typedef struct {
    int size; 
    enum YouShouldDeclareAName {token=0x123456} token; 

    //or
    YouShouldDeclareAName token2;
} Message;
于 2012-06-14T12:11:38.193 に答える
3

5 行目では、enum 型の変数を宣言していません。そのため、コンパイラは実行できる唯一のことを行います: それを無視します。

構造体でその型のメンバーを作成したい場合は、次のように記述します。

enum  {token=0x123456} thetoken;

ただし、このフィールドには有効な値が 1 つしかないことに注意してください。それでよろしいですか?

編集
ああ、あなたの他の質問に答えるために:CまたはC ++としてコンパイルすると、出力に違いが見られません。しかし、構造体定義の書き方には違いがあります。

于 2012-06-14T12:08:18.213 に答える
2

Message::tokenすべてのオブジェクト間で共有される定数を定義しました。共有されているため、単一のオブジェクトのサイズにはカウントされません。

于 2012-06-14T12:06:10.193 に答える
2

他の回答が指摘しているように、列挙を宣言しましたが、たまたまグローバルスコープではなく構造内でそれを行っただけです。保存するものがないため、メモリを使用しません。

その構造体で列挙型のインスタンスを宣言するとしたら...

typedef struct {
    int size; 
    enum {token=0x123456} e; 
} Message;

int main(int argc, char * argv[])
{
    Message m;
    m.size = 30;
    printf("sizeof(m): %d\n",sizeof(m));
}

sizeof(m): 8
Press any key to continue . . .
于 2012-06-14T12:14:39.460 に答える
1

ライン 5:

enum {token=0x123456};

この行は変数を定義していません。これenumは宣言です。これは、コンパイラが 5 行目で唯一の宣言であると不平を言うためです。

適切な使用法は次のとおりです。

enum {xyz=5}  enum_variable_name;

その場合にのみ、コンパイラはこれにスペースを割り当てます。

于 2012-06-14T13:04:21.493 に答える
0

クラス、関数、列挙型と同じように、静的メンバーはオブジェクト空間に格納されません!

于 2012-06-14T12:12:34.997 に答える