字节级别长度描述

时间:2008-08-29 18:38:42

标签: c protocols

我的协议要求长度字段最多为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 个答案:

答案 0 :(得分:4)

你应该为你的长度使用固定宽度的字段。

  • 当接收端的程序必须读取数据包的长度字段时,它如何知道长度停止的位置?
  • 如果数据包的长度可能达到4 GB,那么1-3字节的开销真的很重要吗?
  • 您是否看到您的代码已经变得多么复杂?

答案 1 :(得分: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;
        }

    }

}

答案 2 :(得分: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;
    }  
}

答案 3 :(得分:0)

实际上你只做了四次计算,所以 可读性似乎比效率更重要 。我的方法是使这样的东西更具可读性

  1. 将常用代码提取到函数
  2. 将类似的计算放在一起以使模式更明显
  3. 摆脱中间变量print_zeroes并明确表示输出字节的情况,即使它们为零(即前一个字节非零)
  4. 我已将随机代码块更改为函数并更改了一些变量(下划线在markdown预览屏幕中给我带来麻烦)。我还假设正在传入 bytes ,并且传递它的人将向我们传递一个指针,以便我们可以修改它。

    以下是代码:

    /* 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);
     }
    

    效率稍高一些, 可能 更易于理解,这是对最后四个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);
    
    但是,我同意压缩此字段会使接收状态机过于复杂。但是,如果您无法更改协议,则此代码更容易阅读。

相关问题