<p>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.</p>

<p>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...</p>

<pre><code>{
    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 &amp; 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 &gt;&gt; 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 &amp; 0x00FF0000;
    second = t &gt;&gt; 16;
    if (t || write_zeros) {
        printf("byte 2: 0x%02x\n", second );
        byte_stream[bytes] = second; bytes++;
        write_zeros = 1;
    }

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

    t = n &amp; 0x000000FF;
    fourth = t;
    if (t || write_zeros) {
        printf("byte 4: 0x%02x\n", fourth);
        byte_stream[bytes] = fourth; bytes++;
    }
}
</code></pre>

[{'answer_id': 35027, 'author': 'Daniel Jennings', 'author_id': 3641, 'author_profile': 'https://Stackoverflow.com/users/3641', 'pm_score': 0, 'selected': False, 'text': '<p>Try this loop:</p>\n\n<pre><code>{\n    extern char byte_stream[];\n    int bytes = offset_in_packet;\n    int n = length_of_packet; /* Under 4 billion, so this can be represented in 32 bits. */\n    int t; /* 32-bit number used for temporary storage. */\n    int i;\n\n    unsigned char curByte;\n\n    for (i = 0; i &lt; 4; i++) {\n        t = n &amp; (0xFF000000 &gt;&gt; (i * 16));\n\n        curByte = t &gt;&gt; (24 - (i * 8));\n        if (t || write_zeros)  {\n            printf("byte %d: 0x%02x\\n", i, curByte );\n            byte_stream[bytes] = curByte;\n                            bytes++;\n            write_zeros = 1;\n        }\n\n    }\n\n}\n</code></pre>\n'}, {'answer_id': 35036, 'author': 'Nathan Fellman', 'author_id': 1084, 'author_profile': 'https://Stackoverflow.com/users/1084', 'pm_score': 0, 'selected': False, 'text': '<p>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.<br>\nYou\'re probably better off using a loop like this:  </p>\n\n<pre><code>int i;  \nint write_zeros = 0;  \nfor (i = 3; i &gt;=0 ; --i) {  \n    t = (n &gt;&gt; (8 * i)) &amp; 0xff;  \n    if (t || write_zeros) {  \n        write_zeros = 1;  \n        printf ("byte %d : 0x%02x\\n", 4-i, t);  \n        byte_stream[bytes++] = t;\n    }  \n}\n</code></pre>\n'}, {'answer_id': 35068, 'author': 'Tryke', 'author_id': 773, 'author_profile': 'https://Stackoverflow.com/users/773', 'pm_score': 2, 'selected': False, 'text': '<p>You should really use a fixed-width field for your length.</p>\n\n<ul>\n<li>When the program on the receiving end has to read the length field of your packet, how does it know where the length stops?</li>\n<li>If the length of a packet can potentially reach 4 GB, does a 1-3 byte overhead really matter?</li>\n<li>Do you see how complex your code has already become? </li>\n</ul>\n'}, {'answer_id': 41051, 'author': 'Bart', 'author_id': 4343, 'author_profile': 'https://Stackoverflow.com/users/4343', 'pm_score': 1, 'selected': True, 'text': '<p>Really you\'re only doing four calculations, so <strong><em>readability seems way more important</em></strong> here than efficiency.  My approach to make something like this more readable is to </p>\n\n<ol>\n<li>Extract common code to a function</li>\n<li>Put similar calculations together to make the patterns more obvious</li>\n<li>Get rid of the intermediate variable print_zeroes and be explicit about the cases in which you output bytes even if they\'re zero (i.e. the preceding byte was non-zero)</li>\n</ol>\n\n<p>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).  I\'ve also assumed that <em>bytes</em> is being passed in, and that whoever is passing it in will pass us a pointer so we can modify it.</p>\n\n<p>Here\'s the code:</p>\n\n<pre><code>/* append byte b to stream, increment index */\n/* really needs to check length of stream before appending */\nvoid output( int i, unsigned char b, char stream[], int *index )\n{\n    printf("byte %d: 0x%02x\\n", i, b);\n    stream[(*index)++] = b;\n}\n\n\nvoid answer( char bytestream[], unsigned int *bytes, unsigned int n)\n{\n    /* mask out four bytes from word n */\n    first  = (n &amp; 0xFF000000) &gt;&gt; 24;\n    second = (n &amp; 0x00FF0000) &gt;&gt; 16;\n    third  = (n &amp; 0x0000FF00) &gt;&gt;  8;\n    fourth = (n &amp; 0x000000FF) &gt;&gt;  0;\n\n    /* conditionally output each byte starting with the */\n    /* first non-zero byte */\n    if (first) \n       output( 1, first, bytestream, bytes);\n\n    if (first || second) \n       output( 2, second, bytestream, bytes);\n\n    if (first || second || third) \n       output( 3, third, bytestream, bytes);\n\n    if (first || second || third || fourth) \n       output( 4, fourth, bytestream, bytes);\n }\n</code></pre>\n\n<p>Ever so slightly more efficient, and <strong><em>maybe</em></strong> easier to understand would be this modification to the last four if statements:</p>\n\n<pre><code>    if (n&gt;0x00FFFFFF) \n       output( 1, first, bytestream, bytes);\n\n    if (n&gt;0x0000FFFF) \n       output( 2, second, bytestream, bytes);\n\n    if (n&gt;0x000000FF)  \n       output( 3, third, bytestream, bytes);\n\n    if (1) \n       output( 4, fourth, bytestream, bytes);\n</code></pre>\n\n<p>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.</p>\n'}]
['https://Stackoverflow.com/questions/34977', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3663/']