2016-06-27 12 views
3

私はいくつかのC++ネットワーキングコードを見ていました。 バッファサイジングのためにstd :: maxの代わりにbitwiseを使う

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()関数、またはこれらの6つの構造体のうちの最大サイズの正確なサイズを計算するための3次演算子のいずれかを使用することが期待されます。私は前に上記のイディオムを見たことがないし、それが機能すると自分自身を説得するために停止する必要がありました。

私はこれを初めて勉強して以来、私は一般的にどのように有効であるかを知りたいと思っています。それを行う利点と欠点は何ですか?

私が見ることができることである -

プロ

  • それは常にあなたの最大の構造体のサイズと同じ大きさのサイズ少なくともを与える必要があります。スペースが割高でない場合は、本当に必要なのはどれだけですか。
  • コンパイル時に計算可能に見えます。
  • 非常に古いC++(またはC)コンパイラでも動作するはずです。

詐欺:

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

は、コードがために書かれたもの、コンパイラによっては、特にコンパイラ以来、最適化されている可能性があります。 – refi64

答えて

2

だけで意思を書き留め:

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

物事を難読化には 'プロ' はありません。

+0

は確かに最後の文に同意し、私はこの(私はそれを行う可能性があるため)、「固定」のアイデアに感謝します。しかし、私は、これは私が何とか私の全体の31年のキャリアを見逃しているいくつかのよく知られているイディオムである場合には特に興味があり、そうでない場合、私は長所で良いのハンドルを持っている/短所私はインテリジェントに決定することができますので、(と私の決定をバックアップする)。 –

3

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

しかし、それは非常に混乱し、あなたはそれについてやめなければなりません。さらに、8と7の2つのサイズがある場合、15で終わることになります。これはおそらくあなたが望むものではありません。

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

あなたのコンパイラがその過負荷をサポートしていない場合、それは同じことを達成するために可変引数関数テンプレートを記述するために非常に簡単です:ありがたいことに、std::maxはそうちょうどそれを使用し、initializer_list<T>を取るconstexprオーバーロードがあります。

+0

あなたはその代わりにC++標準バージョンを入れてもらえますか?我々はいくつかの古い(例:C++ 11)をサポートする必要があるコンパイラのバージョンを、そして私たちは唯一のものではありません一般的なケースではと思います。 –

0

これはかなりホッケーに見えます。私はsizeof(union { S1 s1; S2 s2; S3 s3; S4 s4; S5 s5; S6 s6; })を使います。(テストしていません)私はあなたに同意

2

は、私は彼らがそれをやった方法は、ファンキーで次善のだと思います。私はこの種のものを行うために使用される方法は、すべての構造体の労働組合を作り、その後、労働組合のサイズを使用していた

...

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

sizeof(Commands); 

そして、あなたは、構造体と組み合わせる場合あなたのバッファに一つのポインタを設定し、すべてのデータへの容易なアクセスを持つことができます

struct Packet { 
    Header header; 
    Commands command; 
}; 

組合に続いて、あなたのパケットヘッダを、... ...保持

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; 
}; 
(もし言ったとして)コンパイル時に全部を計算することができ3210
関連する問題