2008-08-29 12 views
1

私は32ビットまでの長さのフィールドを必要とするプロトコルを持っており、実行時に与えられたパケットにいくつのバイトがあるかを記述するためには が生成されなければなりません。バイトレベルの長さの説明

以下のコードは一種醜いですが、これをリファクタリングして にすることができますか少し効率的または簡単に理解できますか?問題は コードだけなので 未満255バイト=長さの1バイト、長 など未満65535 = 2バイト...

{ 
    extern char byte_stream[]; 
    int bytes = offset_in_packet; 
    int n = length_of_packet; 
    /* Under 4 billion, so this can be represented in 32 bits. */ 
    int t; 
    /* 32-bit number used for temporary storage. */ 

    /* These are the bytes we will break up n into. */ 
    unsigned char first, second, third, fourth; 

    t = n & 0xFF000000; 
    /* We have used AND to "mask out" the first byte of the number. */ 
    /* The only bits which can be on in t are the first 8 bits. */ 
    first = t >> 24; 
    if (t) { 
     printf("byte 1: 0x%02x\n",first); 
     byte_stream[bytes] = first; bytes++; 
     write_zeros = 1; 
    } 
    /* Now we shift t so that it is between 0 and 255. This is the first, highest byte of n. */ 
    t = n & 0x00FF0000; 
    second = t >> 16; 
    if (t || write_zeros) { 
     printf("byte 2: 0x%02x\n", second); 
     byte_stream[bytes] = second; bytes++; 
     write_zeros = 1; 
    } 

    t = n & 0x0000FF00; 
    third = t >> 8; 
    if (t || write_zeros) { 
     printf("byte 3: 0x%02x\n", third); 
     byte_stream[bytes] = third; bytes++; 
     write_zeros = 1; 
    } 

    t = n & 0x000000FF; 
    fourth = t; 
    if (t || write_zeros) { 
     printf("byte 4: 0x%02x\n", fourth); 
     byte_stream[bytes] = fourth; bytes++; 
    } 
} 
のパケットの長さを記述するのに十分なバイトを生成することです

答えて

0

本当にあなたが4つのしか計算をやっているので、読みやすさは、ここでは効率よりも方法がより重要ようです。このようなものを読みやすくするために私のアプローチは

  1. に機能する中間変数print_zeroesを排除し、約明示的に取得
  2. パターンがより明白にするために一緒に同様の計算を置く
  3. を共通のコードを抽出していますケースは、あなたの出力バイト、それらがゼロ(すなわち、前のバイトが非ゼロであった)

している場合でも、私は関数にランダムなコードブロックを変更し、いくつかの変数(アンダースコアが私を与えているに変更しましたマークダウンプレビューscreのトラブルen)。私はまた、バイトのが渡されていると仮定し、それを渡す人は私たちにポインタを渡してそれを修正することができます。ここで

はコードです:多少エヴァー

/* append byte b to stream, increment index */ 
/* really needs to check length of stream before appending */ 
void output(int i, unsigned char b, char stream[], int *index) 
{ 
    printf("byte %d: 0x%02x\n", i, b); 
    stream[(*index)++] = b; 
} 


void answer(char bytestream[], unsigned int *bytes, unsigned int n) 
{ 
    /* mask out four bytes from word n */ 
    first = (n & 0xFF000000) >> 24; 
    second = (n & 0x00FF0000) >> 16; 
    third = (n & 0x0000FF00) >> 8; 
    fourth = (n & 0x000000FF) >> 0; 

    /* conditionally output each byte starting with the */ 
    /* first non-zero byte */ 
    if (first) 
     output(1, first, bytestream, bytes); 

    if (first || second) 
     output(2, second, bytestream, bytes); 

    if (first || second || third) 
     output(3, third, bytestream, bytes); 

    if (first || second || third || fourth) 
     output(4, fourth, bytestream, bytes); 
} 

より効率的に、そしておそらく文が最後の4場合には、この変更になり、理解しやすい:

if (n>0x00FFFFFF) 
     output(1, first, bytestream, bytes); 

    if (n>0x0000FFFF) 
     output(2, second, bytestream, bytes); 

    if (n>0x000000FF) 
     output(3, third, bytestream, bytes); 

    if (1) 
     output(4, fourth, bytestream, bytes); 

私は同意しますしかし、このフィールドを圧縮すると、受信状態マシンが過度に複雑になる。しかし、プロトコルを変更できない場合、このコードは読みやすくなります。

0

このループを試してください:

{ 
    extern char byte_stream[]; 
    int bytes = offset_in_packet; 
    int n = length_of_packet; /* Under 4 billion, so this can be represented in 32 bits. */ 
    int t; /* 32-bit number used for temporary storage. */ 
    int i; 

    unsigned char curByte; 

    for (i = 0; i < 4; i++) { 
     t = n & (0xFF000000 >> (i * 16)); 

     curByte = t >> (24 - (i * 8)); 
     if (t || write_zeros) { 
      printf("byte %d: 0x%02x\n", i, curByte); 
      byte_stream[bytes] = curByte; 
          bytes++; 
      write_zeros = 1; 
     } 

    } 

} 
+0

この回答は確かに非常にコンパクトなコードソリューションを生成しますが、それがなぜ機能するのかはすぐには分かりません。私が選択した答えは、一目でわかりやすいコードでソリューションをクリアします。 –

0

私はあなたの質問を理解していません。正確に何を数えようとしていますか?私が正しく理解すれば、最も重要でないゼロ以外のバイトを見つけようとしています。
あなたは、このようにループを使用して、おそらく方がいいでしょう:

int i; 
int write_zeros = 0; 
for (i = 3; i >=0 ; --i) { 
    t = (n >> (8 * i)) & 0xff; 
    if (t || write_zeros) { 
     write_zeros = 1; 
     printf ("byte %d : 0x%02x\n", 4-i, t); 
     byte_stream[bytes++] = t; 
    } 
} 
4

あなたが本当にあなたの長さのための固定幅フィールドを使用する必要があります。

  • 受信側のプログラムがパケットの長さフィールドを読み取る必要がある場合、長さがどこで停止するかはどのように分かりますか?
  • パケットの長さが潜在的に4 GBに達する可能性がある場合、1〜3バイトのオーバーヘッドは本当に重要ですか?
  • あなたのコードはすでに複雑になっていますか?