2

最大 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++;
    }
}
4

4 に答える 4

4

長さには固定幅フィールドを実際に使用する必要があります。

  • 受信側のプログラムがパケットの長さフィールドを読み取らなければならない場合、長さがどこで終了するかをどのように知るのでしょうか?
  • パケットの長さが 4 GB に達する可能性がある場合、1 ~ 3 バイトのオーバーヘッドは本当に問題になるのでしょうか?
  • コードがすでにどれほど複雑になっているかわかりますか?
于 2008-08-29T19:08:24.687 に答える
0

実際には4つの計算しか行っていないので、ここでは効率よりも読みやすさがはるかに重要であるように思われます。このようなものをより読みやすくするための私のアプローチは、

  1. 共通コードを関数に抽出する
  2. 同様の計算を組み合わせて、パターンをより明確にします
  3. 中間変数print_zeroesを取り除き、バイトがゼロであっても(つまり、前のバイトがゼロ以外であった場合でも)バイトを出力する場合について明示します。

ランダムコードブロックを関数に変更し、いくつかの変数を変更しました(アンダースコアはマークダウンプレビュー画面で問題を引き起こしています)。また、バイトが渡されていると仮定しました。バイトを渡した人は誰でもポインタを渡して、変更できるようにします。

コードは次のとおりです。

/* 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ステートメントに対するこの変更です。

    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);

ただし、このフィールドを圧縮すると、受信ステートマシンが非常に複雑になることに同意します。ただし、プロトコルを変更できない場合は、このコードの方がはるかに読みやすくなります。

于 2008-09-03T02:14:08.080 に答える
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;
        }

    }

}
于 2008-08-29T18:55:45.997 に答える
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;
    }  
}
于 2008-08-29T18:58:34.663 に答える