sam ray
sam ray

Reputation: 267

C printing bits

I am trying to write a program in C that prints bits of int. for some reason i get wrong values,

void printBits(unsigned int num){
    unsigned int size = sizeof(unsigned int);
    unsigned int maxPow = 1<<(size*8-1);
    printf("MAX POW : %u\n",maxPow);
    int i=0,j;
    for(;i<size;++i){
        for(j=0;j<8;++j){
            // print last bit and shift left.
            printf("%u ",num&maxPow);
            num = num<<1;
        }
    }
}

My question, first why am i getting this result (for printBits(3)).

MAX POW : 2147483648 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 2147483648 214748364 8

second is there a better way to do this ?

Upvotes: 16

Views: 113837

Answers (7)

breiters
breiters

Reputation: 158

How about this Macro:

#define print_bits(x)                                            \
  do {                                                           \
    unsigned long long a__ = (x);                                \
    size_t bits__ = sizeof(x) * 8;                               \
    printf(#x ": ");                                             \
    while (bits__--) putchar(a__ &(1ULL << bits__) ? '1' : '0'); \
    putchar('\n');                                               \
  } while (0)

char c = 3;
int i = -1;
print_bits(c);
print_bits(i);

output:

c: 00000011
i: 11111111111111111111111111111111

This Marco can be used on any primitive datatype and the expression 'x' will be evaluated only once. So you should be safe from side effects.

With the typeof construct you could extend this to structures too:

#define print_bits(x)                                             \
  do {                                                            \
    typeof(x) a__ = (x);                                          \
    char *p__ = (char *)&a__ + sizeof(x) - 1;                     \
    size_t bytes__ = sizeof(x);                                   \
    printf(#x ": ");                                              \
    while (bytes__--) {                                           \
      char bits__ = 8;                                            \
      while (bits__--) putchar(*p__ & (1 << bits__) ? '1' : '0'); \
      p__--;                                                      \
    }                                                             \
    putchar('\n');                                                \
  } while (0)

print_bits((struct in_addr){.s_addr = 0xff00ff00});

output:

(struct in_addr){.s_addr = 0xff00ff00}: 11111111000000001111111100000000

Could be useful e.g. in print debugging.

(typeof is a GNU-extension, use __typeof__ instead if it must work in ISO C programs)

Upvotes: 6

micfan
micfan

Reputation: 840

// example code `ch7-8.c` from the book `明解C言語 3nd` of Shibata Bouyou

#include<stdio.h>

int count_bits(unsigned x)
{
    int bits = 0;
    while (x) {
        if (x & 1U) bits++;
        x >>= 1;
    }
    return bits;
}

int int_bits(void)
{
    return count_bits(~0U);
}

void print_nbits(unsigned x, unsigned n)
{
    int i = int_bits();
    i = (n < i) ? n - 1 : i - 1;
    for (; i >= 0; i--)
        putchar(((x >> i) & 1U) ? '1' : '0');
}

int main(void)
{
    unsigned i;

    for (i = 0; i <= 65535U; i++) {
        printf("%5u ", i);
        print_nbits(i, 16);
        printf(" %06o %04X\n", i, i);
    }

    return 0;
}

output:

    0 0000000000000000 000000 0000
    1 0000000000000001 000001 0001
    2 0000000000000010 000002 0002
    3 0000000000000011 000003 0003
    4 0000000000000100 000004 0004
    5 0000000000000101 000005 0005
    6 0000000000000110 000006 0006
    7 0000000000000111 000007 0007
    8 0000000000001000 000010 0008
    9 0000000000001001 000011 0009
   10 0000000000001010 000012 000A
   11 0000000000001011 000013 000B
   12 0000000000001100 000014 000C
   13 0000000000001101 000015 000D
   14 0000000000001110 000016 000E
   15 0000000000001111 000017 000F
   16 0000000000010000 000020 0010

Upvotes: 1

LittleEaster
LittleEaster

Reputation: 601

I guess You can remove some code and

void printB(unsigned int num){
    unsigned int size = sizeof(unsigned int);
    int i;
    for(i = size*8-1; i>= 0; i--){
        printf("%u",(num >>i) & 1 );
    }
    printf("\n");
}

Upvotes: 1

Nikhil Vidhani
Nikhil Vidhani

Reputation: 729

void print_bits(unsigned int x)
{
    int i;
    for(i=8*sizeof(x)-1; i>=0; i--) {
        (x & (1 << i)) ? putchar('1') : putchar('0');
    }
    printf("\n");
}

Upvotes: 1

Adam Davis
Adam Davis

Reputation: 93565

To address point two, I'd consider the following, which is simplified a bit for ease of understanding.

void printBits(unsigned int num)
{
   for(int bit=0;bit<(sizeof(unsigned int) * 8); bit++)
   {
      printf("%i ", num & 0x01);
      num = num >> 1;
   }
}

Upvotes: 12

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726659

You are calculating the result correctly, but you are not printing it right. Also you do not need a second loop:

for(;i<size*8;++i){
    // print last bit and shift left.
    printf("%u ",num&maxPow ? 1 : 0);
    num = num<<1;
}

If you'd like to show off, you could replace the conditional with two exclamation points:

printf("%u ", !!(num&maxPow));

Upvotes: 26

Daniel Fischer
Daniel Fischer

Reputation: 183908

The result you get is because num&maxPow is either 0 or maxPow. To print 1 instead of maxPow, you could use printf("%u ", num&maxPow ? 1 : 0);. An alternative way to print the bits is

while(maxPow){
    printf("%u ", num&maxPow ? 1 : 0);
    maxPow >>= 1;
}

i.e. shifting the bitmask right instead of num left. The loop ends when the set bit of the mask gets shifted out.

Upvotes: 10

Related Questions