Search code examples
cbit-manipulation

bit programing in C


I am new to bits programming in C and finding it difficult to understand how ipv4_to_bit_string() in below code works. Can anyone explain that, what is happening when I pass integer 1234 to this function. Why integer is right shifted at 24,16,8 and 4 places?

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct BIT_STRING_s {
    uint8_t *buf;       /* BIT STRING body */
    size_t size;        /* Size of the above buffer */
    int bits_unused;    /* Unused trailing bits in the last octet (0..7) */
} BIT_STRING_t;

BIT_STRING_t     tnlAddress;


void ipv4_to_bit_string(int i, BIT_STRING_t *p)
{
    do {
        (p)->buf = calloc(4, sizeof(uint8_t));              
        (p)->buf[0] = (i) >> 24 & 0xFF;                  
        (p)->buf[1] = (i) >> 16 & 0xFF;                  
        (p)->buf[2] = (i) >> 8 & 0xFF;                   
        (p)->buf[3] = (i) >> 4 & 0xFF;                   
        (p)->size = 4;
        (p)->bits_unused = 0;
    } while(0);
}


int main()
{
    BIT_STRING_t *p = (BIT_STRING_t*)calloc(1, sizeof(BIT_STRING_t));
    ipv4_to_bit_string(1234, p);
}

Solution

  • An IPv4 address is four eight-bit pieces that have been put together into one 32-bit piece. To take the 32-bit piece apart into the four eight-bit pieces, you extract each eight bits separately. To extract one eight-bit piece, you shift right by 0, 8, 16, or 24 bits, according to which piece you want at the moment, and then mask with 0xFF to take only the low eight bits after the shift.

    The shift by 4 instead of 0 appears to be an error.

    The use of an int for the 32-bit piece appears to be an error, primarily because the high bit may be set, which indicates the int value is negative, and then the right-shift is not fully defined by the C standard; it is implementation-defined. An unsigned type should be used. Additionally, int is not necessarily 32 bits; it is preferable to use uint32_t, which is defined in the <stdint.h> header.