简体   繁体   English

字节级别长度描述

[英]Byte level length description

I have a protocol that requires a length field up to 32-bits, and it must be generated at runtime to describe how many bytes are in a given packet. 我有一个协议,需要一个长度为32位的字段,并且必须在运行时生成它来描述给定数据包中有多少字节。

The code below is kind of ugly but I am wondering if this can be refactored to be slightly more efficient or easily understandable. 下面的代码有点难看,但我想知道这是否可以重构为更高效或易于理解。 The problem is that the code will only generate enough bytes to describe the length of the packet, so less than 255 bytes = 1 byte of length, less than 65535 = 2 bytes of length etc... 问题是代码只会生成足够的字节来描述数据包的长度,所以小于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++;
    }
}

You should really use a fixed-width field for your length. 你应该为你的长度使用固定宽度的字段。

  • When the program on the receiving end has to read the length field of your packet, how does it know where the length stops? 当接收端的程序必须读取数据包的长度字段时,它如何知道长度停止的位置?
  • If the length of a packet can potentially reach 4 GB, does a 1-3 byte overhead really matter? 如果数据包的长度可能达到4 GB,那么1-3字节的开销真的很重要吗?
  • Do you see how complex your code has already become? 你看到你的代码已经变得多么复杂了吗?

Try this loop: 试试这个循环:

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

    }

}

I'm not sure I understand your question. 我不确定我理解你的问题。 What exactly are you trying to count? 你到底在想什么? If I understand correctly you're trying to find the Most Significant non-zero byte. 如果我理解正确,你试图找到最重要的非零字节。
You're probably better off using a loop like this: 你可能最好使用这样的循环:

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

Really you're only doing four calculations, so readability seems way more important here than efficiency. 实际上你只做了四次计算,所以可读性似乎比效率更重要 My approach to make something like this more readable is to 我使这样的东西更具可读性的方法是

  1. Extract common code to a function 将常用代码提取到函数中
  2. Put similar calculations together to make the patterns more obvious 将类似的计算放在一起,使模式更加明显
  3. Get rid of the intermediate variable print_zeroes and be explicit about the cases in which you output bytes even if they're zero (ie the preceding byte was non-zero) 摆脱中间变量print_zeroes并明确表示输出字节的情况,即使它们为零(即前一个字节非零)

I've changed the random code block into a function and changed a few variables (underscores are giving me trouble in the markdown preview screen). 我已将随机代码块更改为函数并更改了一些变量(下划线在markdown预览屏幕中给我带来麻烦)。 I've also assumed that bytes is being passed in, and that whoever is passing it in will pass us a pointer so we can modify it. 我还假设正在传入字节 ,并且传递它的人将向我们传递一个指针,以便我们可以修改它。

Here's the code: 这是代码:

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

Ever so slightly more efficient, and maybe easier to understand would be this modification to the last four if statements: 如此高效一点, 也许更容易理解的是对最后四个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);

I agree, however, that compressing this field makes the receiving state machine overly complicated. 但是,我同意压缩此字段会使接收状态机过于复杂。 But if you can't change the protocol, this code is much easier to read. 但是,如果您无法更改协议,则此代码更易于阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM