Reputation: 33
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
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
Reputation: 21542
A couple of things:
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.
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