0

次のような不完全なサーバーのコードを指定します。

enum class Command : uint32_t {
    LOGIN,
    MESSAGE,
    JOIN_CHANNEL,
    PART_CHANNEL,
    INVALID
};

Command::LOGIN整数に変換すると常に同じ値になると期待できますか?

  • コンパイラ間で?
  • コンパイラのバージョン間で?
  • 別の列挙を追加すると?
  • 列挙を削除すると?

変換Command::LOGINは次のようになります。

uint32_t number = static_cast<uint32_t>(Command::LOGIN);

私がここでやっていることに関するいくつかの追加情報。この列挙は、それをサーバー/クライアントに送信する整数に変換することにより、ネットワークに供給されます。数値が常に同じである限り、数値が何であるかは特に気にしません。同じままではない場合は、明らかに、通常の方法で自分の番号を提供する必要があります。

現在、コードのコンパイルに使用されたコンパイラによって変わるのではないかとこっそり疑っていますが、確実に知りたいです。

おまけの質問: コンパイラ/言語は、どの番号を使用するかをどのように決定しCommand::LOGINますか?

この質問を送信する前に、たとえば 3137527848 から 0 へ、またはその逆に変更されていることに気付きました。この数がどのように決定され、その数がどのように、またはなぜ変化しているのかについて、私はまだ興味があります。

4

3 に答える 3

2

C++11 標準 (というか、n3485) から:

[dcl.enum]/2

最初の列挙子に初期化子がない場合、対応する定数の値はゼロです。初期化子のないenumerator-definitionは、前の列挙子の値を 1 だけ増やした値を列挙子に与えます。

さらに、[expr.static.cast]/9

スコープ列挙型の値は、整数型に明示的に変換できます。元の値が指定された型で表現できる場合、値は変更されません。

uint32_t列挙子の値は;で表すことができることは明らかだと思います。そうでない場合、[dcl.enum]/5 は、「列挙子の初期化値を基になる型で表すことができない場合、プログラムの形式が正しくありません」と言います。

そのため、基になる型を変換に使用する限り (明示的にまたは経由で)、これらの列挙子の値は、それらの前に(同じ列挙で)列挙子を追加したり、順序を変更したりしない限りstd::underlying_type<Command>::type固定されます。

Nicolas Louis Guillemoが指摘したように、値を転送するときはエンディアンが異なる可能性があることに注意してください。

于 2013-09-11T22:58:22.860 に答える
2

列挙型定数に明示的な整数値を割り当てると、整数型に変換するときに常に同じ値になることが保証されます。

次のようなことをしてください:

enum class Command : uint32_t {
    LOGIN = 12,
    MESSAGE = 46,
    JOIN_CHANNEL = 5,
    PART_CHANNEL = 0,
    INVALID = 42
};

値を明示的に指定しない場合、値は暗黙的に設定され、ゼロから始まり、リストを下に移動するたびに 1 ずつ増加します。

ドラフトn3485からの引用:

[dcl.enum] パラグラフ 2

enum のみの enum-key で宣言された列挙型はスコープなし列挙であり、その列挙子はスコープなし列挙子です。enum-keys enum クラスと enum 構造体は意味的に同等です。これらのいずれかで宣言された列挙型はスコープ付き列挙であり、その列挙子はスコープ付き列挙子です。[...] 列挙子リストの識別子は定数として宣言され、定数が必要な場所に表示できます。= を伴う列挙子定義は、関連する列挙子に定数式によって示される値を与えます。最初の列挙子に初期化子がない場合、対応する定数の値はゼロです。初期化子のない enumerator-definition は、前の列挙子の値を 1 だけ増やした値を列挙子に与えます

これに依存することの欠点は、リストの順序が将来何らかの形で変更された場合、コードが静かに壊れる可能性があることです。そのため、明確にすることをお勧めします。

于 2013-09-11T22:42:55.607 に答える
1

Command::LOGIN は、リストの最初の列挙である限り、常に 0 になります。コンピューターがビッグ エンディアンを使用しているかリトル エンディアンを使用しているかによって、バイナリ表現が異なるため、残りの列挙型には注意してください。

于 2013-09-11T22:41:20.987 に答える