dave
dave

Reputation: 33

Unable to convert a binary to decimal

My aim is to have a decimal which has same leading ones in binary as the user specifies, which is stored in the unsigned long variable mask; the remaining bits would be set to zero.

int mask; 
scanf("%d",&mask);
unsigned long subnetMask = 0;
int counter = 31,a;
for(int a = mask, a > 0; a--) {
     subnetMask += pow(2,counter);
     counter--;
}
printf("%ld",subnetMask);

Now, when the user types in 24, the binary string for the mask is 11111111 11111111 11111111 00000000, and I am trying to convert that into base 10.

Instead of giving me the correct output of 4294967040 it gives me -128. I know there is a memory overflow in some parts, but I can't figure out where. I have tried several things, such as replacing subnetMask's data type with int and long.

Upvotes: 3

Views: 129

Answers (2)

DKing
DKing

Reputation: 21

You can solve the original problem without looping, on 32-bit or larger machines:

unsigned long subnetMask = mask ? - (1<<(32 - mask)) : 0;

Also, subnetMask doesn't have to be long on 32-bit machines. The correctness of the expression is shown with this code:

 for(int mask = 0; mask < 33; mask++)
{
    unsigned subnetMask = mask ? - (1<<(32 - mask)) : 0;

    printf("%2d => %08x = %u (decimal)\n",  mask, subnetMask, subnetMask );
}

Upvotes: 2

Govind Parmar
Govind Parmar

Reputation: 21542

A couple of things:

  1. The %ld format specifier expects a signed int. The number 0b11111111111111111111111100000000 definitely looks like a negative number when interpreted as a signed number in two's complement since the left part of the bit string is all 1s, so it doesn't sound too surprising that the input "4294967040" printed out as -128. What you're looking for is the %lu format specifier.

  2. pow returns a double, not an int or an unsigned long. You probably want to cast the pow result to an int, or better yet, just use 1UL << counter to get the same result as an unsigned long automatically.

Upvotes: 1

Related Questions