1

I want to convert a unsigned integer into an array of 48 bit binary representation,if the result is less than 48 bit then I need to zero out the rest of the bits. Here's the function:

char *getBinary(unsigned int num)
{
char* bstring;
int i;
bstring = (char*) malloc(sizeof(char) * 49);
assert(bstring != NULL);

bstring[48] = '\0';
for( i = 0; i < 48; i++ )
{
    bstring[48 - 1 - i] = (num == ((1 << i) | num)) ? '1' : '0';
}
return bstring;
}

And in the main function:

unsigned int nbr1=3213816984;
char * bi=getBinary(nbr1);

The result should be:

000000000000000010111111100011101111010010011000

But instead I got:

111101001001100010111111100011101111010010011000

Why I can't zero out the bit that's more than 32 bits?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • 1
    Because `unsigned int num` is a 32-bit quantity. You'd have to cast to a 64-bit quantity such as `unsigned long long` before shifting. – Jonathan Leffler Apr 17 '17 at 02:40
  • @JonathanLeffler Hi thanks for the response! I tried to use unsigned long long but still getting the same result. – GhostKid Yao Apr 17 '17 at 02:44
  • You have to change the interface to the function so it accepts a 64-bit (or bigger than 32-bit) value — you're essentially never going to get more than 32-bits on any normal platform. The `1` in `1 << i` is also an `int` and hence 32-bit. You might need to use `1ULL << i` there. Also, `num == ((1ULL << i) | num)` probably isn't doing what you want. You might need `((1ULL << i) & num) != 0` or thereabouts. – Jonathan Leffler Apr 17 '17 at 02:48
  • 1
    Hi, Thank you so much I tried num == ((1ULL << i) | num) and the result is correct. But I don't understand the ((1ULL << i) & num) != 0 part and why is this better? – GhostKid Yao Apr 17 '17 at 02:54
  • Hmmm...it's an unusual idiom (I don't remember seeing it before), but I guess `num == ((1ULL << i) | num)` does work. It checks that `num` doesn't change when you set the i'th bit in the number. The `num & (1ULL << i)` notation extracts the i'th bit from the number — hence the alternative test I wrote. – Jonathan Leffler Apr 17 '17 at 02:58
  • [Don't cast the result of `malloc` in C](http://stackoverflow.com/q/605845/995714) – phuclv Apr 17 '17 at 04:20

1 Answers1

1

The behavior you are invoking in undefined. That is, the C standard does not prescribe what is going to happen when you shift a number farther than its default bit width. So the compiler writer can do whatever they want.

In your example, it seems like the behavior is to "wrap around" the bit, such that 1 << 32 becomes 1 << 0, and so the upper 16 bits appear to be a repeat of the lower 16 bits.

As @Jonathan Leffler mentioned in a comment, you need to use a data type that is wide enough to support your 48-bit scheme, or you need to take steps to break your 48-bit input into 32-bit pieces, whichever you prefer.

Edit:

Based on your comment, I will point out that 1 is an integer literal. It has a type. So the result of the expression 1 << i also has a type, and it is derived from the type of 1.

The best thing for you to do, if you want to operate on unsigned-long-long numbers, is to put everything into some variables of the correct type, as soon as you can.

unsigned long long ONE = 1;

ONE << i

The alternative - using constant literals - involves the ULL suffix:

1ULL << i
aghast
  • 14,785
  • 3
  • 24
  • 56