4

私はいくつかの C++ ネットワーク コードを見ていました。バッファの大きさを調べに行ったところ、次のようなことがわかりました。

static const uint32_t MAX_COMMAND_BUFFER =
        sizeof(struct S1) | sizeof(struct S2) | sizeof(struct S3) |
        sizeof(struct S4) | sizeof(struct S5) | sizeof(struct S6);

ここでの基本的な考え方は、バッファーにこれら 6 つの構造体のいずれかを含めることができるということです。これは外側のスコープで宣言されているため、後で外側のスコープのuint8_t配列サイズなどに使用できます。

通常、ここでは、std::max() 関数または 3 項演算子を使用して、これら 6 つの構造体のうち最大のものの正確なサイズを計算するものを期待します。私は上記のイディオムを見たことがなく、それが機能することを確信するために立ち止まる必要がありました。

私はこれに慣れていないので、一般的に、これがどれほど有効であり、それを行うことの利点と欠点は何かを知りたい.

私が見ることができるのは -

プロ:

  • 構造体の最大サイズと少なくとも同じ大きさのサイズを常に提供する必要があります。スペースが限られていなければ、本当に必要なのはこれだけです。
  • コンパイル時に計算できるようです。
  • 非常に古い C++ (または C) コンパイラでも動作するはずです。

短所:

  • 必要なサイズのほぼ 2 倍になる場合があります。
  • これにより、人間がオフラインでバッファーの大きさを正確に把握することがはるかに困難になります。
  • その奇妙な/予期しない。
4

4 に答える 4

3

MAX_COMMAND_BUFFERこれらの構造体のすべてのサイズの最大値と少なくとも同じ大きさになるという意味で有効です。これを確認するのは簡単です -|すべてのサイズを一緒にビット単位で処理すると、最大サイズと同じビットを持つ値が得られます。

しかし、それは非常に紛らわしいので、立ち止まって考えなければなりません。さらに、8 と 7 の 2 つのサイズがある場合、最終的に 15 になりますが、これはおそらく望んでいないことです。ありがたいことに、std::maxconstexpr取るオーバーロードがあるinitializer_list<T>ので、それを使用してください:

static constexpr size_t MAX_COMMAND_BUFFER =
//               ^^^^^^
        std::max({sizeof(struct S1), sizeof(struct S2), ..., sizeof(struct S6)});

コンパイラがそのオーバーロードをサポートしていない場合、可変引数関数テンプレートを記述して同じことを行うのは非常に簡単です。

于 2016-06-27T20:56:04.713 に答える
2

私はあなたに同意します。彼らのやり方はファンキーで最適ではないと思います。

私がこの種のことを行っていた方法は、すべての構造体の結合を作成し、結合のサイズを使用することでした...

union Commands {
  S1 s1;
  S2 s2;
  ...
  S6 s6;
};

sizeof(Commands);

そして、これをパケットヘッダーを保持する構造体と組み合わせると、その後にユニオンが続きます...

struct Packet {
  Header header;
  Commands command;
};

バッファに 1 つのポインタを設定して、すべてのデータに簡単にアクセスできます...

Packet *packet = (Packet)&buf[0];
switch(packet->header.command_type) {
  case COMMAND_DO_STUFF:
    printf("%d\n", packet->command.s1.stuff);
    break;
  case COMMAND_QUIT:
    ..
    break;
};
于 2016-06-27T21:12:12.057 に答える
2

意図を書き留めてください:

#include <algorithm>
struct S1 {};
struct S2 {};
struct S3 {};
int main() {
    static const unsigned maximum = std::max({sizeof(S1), sizeof(S2), sizeof(S3) /*, ... */});
}

物事を難読化することに「プロ」はいません。

于 2016-06-27T20:55:55.197 に答える
0

それはかなりばかげているように見えます。私は使用しますsizeof(union { S1 s1; S2 s2; S3 s3; S4 s4; S5 s5; S6 s6; })。(未検証)

于 2016-06-27T20:57:11.483 に答える