web-dev-qa-db-ja.com

sizeof(enum)== sizeof(int)、常にですか?

Sizeof(enum)== sizeof(int)、常にですか?

  • それともコンパイラに依存していますか?
  • コンパイラはWordの長さ(メモリアライメント)に最適化されているため、y intは特定のコンパイラのWordサイズです。列挙型を使用しても、Wordに揃えられるため、処理のペナルティがないということですか?
  • すべての戻りコードを列挙型に入れても、戻り値の型をチェックする際に名前だけを取得するので、心配する必要はありません。これが当てはまる場合、メモリを節約するため#DEFINEの方が優れています。

通常の慣行は何ですか?これらの戻り値の型をネットワーク経由で転送する必要があり、もう一方の端で何らかの処理を行う必要がある場合、enums /#defines/const intをどのように使用しますか。

編集-コンパイラはマクロをシンボリックにリンクしないので、ネット上で確認するだけで、人々はその後どのようにデバッグし、整数値をヘッダーファイルと比較しますか?

From Answers —明確にする必要があるため、この行を下に追加しています—

「つまり、実装定義であり、sizeof(enum)可能性があります sizeof(char)、つまり1です。」

  • コンパイラが列挙型の値の範囲をチェックしてからメモリを割り当てるという意味ではありませんか。私はそうは思わない、もちろん私は知らない。誰かが「可能性がある」とは何か説明してください。
58
Vivek Sharma

コンパイラに依存し、列挙型によって異なる場合があります。以下はセマンティクスです

enum X { A, B };

// A has type int
assert(sizeof(A) == sizeof(int));

// some integer type. Maybe even int. This is
// implementation defined. 
assert(sizeof(enum X) == sizeof(some_integer_type));

C99の「整数型」には拡張整数型も含まれる場合があることに注意してください(ただし、実装は、提供する場合は文書化する必要があります)。列挙のタイプは、任意の列挙子の値を格納できるタイプです(この場合はAおよびB)。

列挙型の使用にはペナルティはないと思います。列挙子も整数定数式であるため(たとえば、静的変数またはファイルスコープ変数を初期化するために使用できます)、可能な場合はマクロよりも優先します。

列挙子にはランタイムメモリは必要ありません。列挙型の変数を作成する場合にのみ、ランタイムメモリを使用できます。列挙子をコンパイル時定数と考えてください。

列挙子の値を格納できる型を使用し(事前に大まかな値の範囲を知っている必要があります)、それにキャストし、ネットワーク経由で送信します。タイプはint32_tのような固定幅のものであることが望ましいので、異なるマシンが関係しているときに競合することはありません。または、番号を印刷し、反対側でスキャンして、これらの問題のいくつかを取り除きます。


編集への応答

さて、コンパイラはサイズを使用する必要はありません。見やすいのは、値の符号が重要であることです。符号なしの型は、一部の計算でパフォーマンスが大幅に向上する可能性があります。以下は、私のボックスでのGCC 4.4.0の動作です

int main(void) {
  enum X { A = 0 };
  enum X a; // X compatible with "unsigned int"
  unsigned int *p = &a;
}

ただし、-1を割り当てると、GCCはintと互換性のある型としてXを使用することを選択します

int main(void) {
  enum X { A = -1 };
  enum X a; // X compatible with "int"
  int *p = &a;
}

GCCのオプション--short-enumsを使用すると、すべての値に適合する最小のタイプが使用されます。

int main() {
  enum X { A = 0 };
  enum X a; // X compatible with "unsigned char"
  unsigned char *p = &a;
}

C99、6.7.2.2p4によると

各列挙型は、char、符号付き整数型、または符号なし整数型と互換性があります。タイプの選択は実装定義です108)が、列挙のすべてのメンバーの値を表現できなければなりません。 [...]

脚注108が追加

実装では、すべての列挙定数が見つかるまで、どの整数型の選択を遅らせることができます。

したがって、実装定義であり、sizeof(enum)はsizeof(char)と等しい場合があります。つまり、1です。

いくつかの小さな範囲の整数のサイズを選択する場合、常にのペナルティがあります。メモリを小さくすると、おそらく処理のペナルティがあります。大きくすると、スペースにペナルティが生じます。これは時間と空間のトレードオフです。

エラーコードは、拡張可能である必要があるため、通常は#definesです。異なるライブラリが新しいエラーコードを追加する場合があります。列挙型ではできません。

19

Sizeof(enum)== sizeof(int)、常に

ANSI C規格は次のように述べています。

各列挙型は、char、符号付き整数型、または符号なし整数型と互換性があります。タイプの選択は実装定義です。 (6.7.2.2列挙指定子)

だから、それはノーという意味だと思います。

これが当てはまる場合、メモリを節約するため#DEFINEの方が優れています。

Enumを使用するよりも、defineを使用するとメモリを節約する方法は何ですか?列挙型は、コンパイラにより多くの情報を提供できる単なる型です。実際の結果の実行可能ファイルでは、プリプロセッサが#define inで作成されたマクロをその値に変換するように、整数に変換されます。

通常の練習は何ですか。ネットワーク上でこれらの戻り値の型を転送する必要があり、もう一方の端でいくつかの処理を行う必要がある場合

ネットワークを介して値を転送し、もう一方の端で値を処理する場合は、プロトコルを定義する必要があります。各タイプのビット単位のサイズ、エンディアンネス(バイトの順序)を決定し、クライアントコードとサーバーコードの両方でそれを確実に順守してください。また、たまたま動作するからといって、それが正しいと思っているだけではありません。たとえば、選択したクライアントプラットフォームとサーバープラットフォームのエンディアンが一致する場合もありますが、必ずしもそうとは限りません。

13
IRBMe

いや.

例: CodeSourceryコンパイラ

次のような列挙型を定義する場合:

enum MyEnum1 {
A=1,
B=2,
C=3
};
// will have the sizeof 1 (fits in a char)

enum MyEnum1 {
A=1,
B=2,
C=3,
D=400
};
// will have the sizeof 2 (doesn't fit in a char)

詳細 メーリングリストから

4
INS

一部のコンパイラでは、列挙のサイズは、列挙に含まれるエントリの数に依存します。 (255エントリ未満=>バイト、255エントリ以上int)しかし、これはコンパイラとコンパイラ設定に依存します。

2
nuriaion