C 字节级长度描述

C 字节级长度描述,c,protocols,C,Protocols,我有一个协议,要求长度字段最多32位,它必须是 在运行时生成,用于描述给定数据包中的字节数 下面的代码有点难看,但我想知道是否可以将其重构为 稍微高效一点或容易理解。问题是 代码只会生成足够的字节来描述数据包的长度,所以 小于255字节=1字节长度,小于65535=2字节长度 等等 尝试以下循环: { extern char byte_stream[]; int bytes = offset_in_packet; int n = length_of_packet; /*

我有一个协议,要求长度字段最多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. */
    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;
        }

    }

}
{
外部字符字节_流[];
int bytes=数据包中的偏移量;
int n=小于40亿的数据包长度;/*因此可以用32位表示*/
int t;/*用于临时存储的32位数字*/
int i;
无符号字符;
对于(i=0;i<4;i++){
t=n&(0xFF000000>>(i*16));
courbyte=t>>(24-(i*8));
if(t | |写| u零){
printf(“字节%d:0x%02x\n”,i,curByte);
字节流[字节]=字节;
字节++;
写入0=1;
}
}
}

我不太明白你的问题。你到底想数什么?如果我理解正确,您正在尝试查找最重要的非零字节。
您最好使用这样的循环:

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

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

  • 当接收端的程序必须读取数据包的长度字段时,它如何知道长度在哪里停止
  • 如果数据包的长度可能达到4GB,那么1-3字节的开销真的很重要吗
  • 你看到你的代码已经变得多么复杂了吗
实际上,您只进行了四次计算,因此可读性似乎比效率更重要。我想让这样的东西更具可读性的方法是

  • 将公共代码提取到函数中
  • 将类似的计算放在一起,使模式更加明显
  • 去掉中间变量print_zero,并明确说明输出字节的情况,即使它们为零(即前面的字节为非零)
  • 我已将随机代码块更改为一个函数,并更改了一些变量(下划线在标记预览屏幕中给我带来了麻烦)。我还假设正在传入字节,传入字节的人将向我们传递一个指针,以便我们可以修改它

    代码如下:

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

    但是,我同意压缩这个字段会使接收状态机过于复杂。但是,如果您不能更改协议,则此代码更易于阅读。

    虽然此答案确实产生了一个非常紧凑的代码解决方案,但其工作原理的本质还不清楚。我选择的答案通过代码使解决方案清晰易懂,一目了然。
        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);