1

I'm trying to print the binary representation of a long in order to practice bit manipulation and setting various bits in the long for a project I am working on. I successfully can print the bits on ints but whenever I try to print 64 bits of a long the output is screwy. Here is my code:

#include <stdio.h> 

void printbits(unsigned long n){
    unsigned long i; 
    i = 1<<(sizeof(n)*4-1);
    while(i>0){
         if(n&1)
              printf("1"); 
         else 
              printf("0"); 
         i >>= 1; 
}

int main(){
    unsigned long n=10; 
    printbits(n); 
    printf("\n"); 
}

My output is 0000000000000000000000000000111111111111111111111111111111111110. Thanks for help!

pigsploof
  • 35
  • 6

3 Answers3

4
  • 4 isn’t the right number of bits in a byte
  • Even though you’re assigning it to an unsigned long, 1 << … is an int, so you need 1UL
  • n&1 should be n&i
  • There’s a missing closing brace

Fixes only:

#include <limits.h>
#include <stdio.h> 

void printbits(unsigned long n){
    unsigned long i; 
    i = 1UL<<(sizeof(n)*CHAR_BIT-1);
    while(i>0){
         if(n&i)
              printf("1"); 
         else 
              printf("0"); 
         i >>= 1;
    }
}

int main(){
    unsigned long n=10; 
    printbits(n); 
    printf("\n"); 
}

And if you want to print a 64-bit number specifically, I would hard-code 64 and use uint_least64_t.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 1
    Ry-, for fun, to cope with those padded `unsigned long` implementations, (rotting in a computer graveyard), code could use the portable `i = ULONG_MAX - ULONG_MAX/2;` – chux - Reinstate Monica Oct 17 '18 at 05:07
2

The problem is that i = 1<<(sizeof(n)*4-1) is not correct for a number of reasons.

  1. sizeof(n)*4 is 32, not 64. you probably want sizeof(n)*8
  2. 1<<63 may give you overflow because 1 may be 32-bits by default. You should use 1ULL<<(sizeof(n)*8-1)
  3. unsigned long is not necessarily 64 bits. You should use unsigned long long

If you want to be extra thorough, use sizeof(n) * CHAR_BIT (defined in <limits.h>).

In general, you should use stdint defines (e.g. uint64_t) whenever possible.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Kon
  • 4,023
  • 4
  • 24
  • 38
  • 1
    You want `sizeof(n) * CHAR_BIT` (defined in ``). And if you want a type that's exactly 64 bits, use `uint64_t`. If you want at least 64 bits, use `unsigned long long` or `uint_least64_t`. – Keith Thompson Oct 16 '18 at 23:10
  • 2
    `1ULL` would be better (`1LL << 63` is undefined behaviour) – M.M Oct 16 '18 at 23:11
0

The following should do what you want:

#include <stdio.h>

void printbits(unsigned long number, unsigned int num_bits_to_print)
{
    if (number || num_bits_to_print > 0) {
        printbits(number >> 1, num_bits_to_print - 1);
        printf("%d", number & 1);
    }
}

We keep calling the function recursively until either we've printed enough bits, or we've printed the whole number, whichever takes more bits.

wrapping this in another function directly does exactly what you want:

void printbits64(unsigned long number) {
    printbits(number, 64);
}
CoffeeTableEspresso
  • 2,614
  • 1
  • 12
  • 30