Search code examples
cbitwise-operatorsbitmask

Convert decimal string IP mask to unsigned int with trailing zeros


I get a mask as a string that I retrieve using strtol and strtok and that I want to save in an unsigned int x, trail with zeros, and & it with an IP represented also as unsigned int in order to keep the MSBs only (At the end I'm going to compare that IP with another).

My idea was to set all the bits of x, and then turn off all bits placed after the mask size:

#define IPV4_LENGTH 32

//subent is "123.34.45.66/31"

curr_IP->address = malloc(sizeof (struct in_addr));
token = strtok(subnet, "/");
inet_aton(token, curr_IP->address);
long mask  = strtol(strtok(NULL, "/"), NULL, 10);
curr_IP->x = -1;
for(long i=mask; i<=IPV4_LENGTH; i++){
    curr_IP->x &= ~(1U << i);
}

Example: if mask = 31, I want to end with 11111111111111111111111111111110 represented in unsigned int -> FFFFFFFE in HEX

P.S mask can't be 0

UPDATE: Memory view after curr_IP->x = -1;

We can see it indeed sets up all the bits

enter image description here

Memory view after curr_IP->x &= ~(1U << i); when i = 31

expected fffffffe

enter image description here


Solution

  • I choose a different approach; turning off the mask and then setting the relevant bits to 1.

    long mask  = strtol(strtok(NULL, "/"), NULL, 10);
    curr_IP->x = 0; //mask to 0
    for(long i=IPV4_LENGTH - mask; i<IPV4_LENGTH; i++){
        curr_IP->x |= (1U << i); //Sets the ith bit of the mask
    }
    

    Edit: As Morten Jensen pointed, it is better not to mix signed and unsigned integers, so the corrected code looks like that:

    unsigned long mask  = strtol(strtok(NULL, "/"), NULL, 10);
    curr_IP->x = 0; //mask to 0
    for(unsigned long i=IPV4_LENGTH - mask; i<IPV4_LENGTH; i++){
        curr_IP->x |= (1U << i); //Sets the ith bit of the mask
    }
    

    Also, I struggled with debugging the code myself because I used the Memory view without realizing that I should read it from right to left.

    In picture #2, I thought that I got fffffff7 when it was actually 7fffffff