Junius L
Junius L

Reputation: 16152

How to print bits in c

I'm writing a function to print bits in c, I'm only allowed to use write function. my function doesn't work for other numbers.

void    print_bits(unsigned char octet)
{
    int oct;
    int div;

    div = 128;
    oct = octet;
    while (!(div <= 1))
    {
        if (div <= oct)
        {
            write(1, "1", 1);
            oct = oct % div;
        }
        else
        {
            write(1, "0", 1);
            div = div / 2;
        }
    }
}

live code

Upvotes: 2

Views: 20306

Answers (5)

user15278186
user15278186

Reputation: 39

This solution sets a padding that auto adjusts with the parameter type. A long long ensures that most numbers will be trivial to handle. It has a static buffer so the caller has no mem to release. Should be fairly versatile as it formats the number into a char * for use with printf or puts as needed. Just a basic descending do while loop that should be simple for the compiler to unroll, as printf can format the rest as needed. Optimized version of Is there a printf converter to print in binary format?

inline char* binstr(long long number) {
  # define BINSTR_BODY_DEFINITION                                                                       \
    static const char BYTE_BOUNDRY = 8;  /* reuse fixed byte boundary to determine padding `*/      \
    static const char ZERO = '0';        /* reuse fixed byte 0 */                                   \
    static const char ONE = '1';         /* reuse fixed byte 1 */                                   \
    static const char digits_length = sizeof number * BYTE_BOUNDRY;                                 \
 /* reuse predetermined byte digits length */                                                   \
    static char src[digits_length + 1];  /* instantiate reusable array */                           \
    int i = digits_length;               /* instantiate temp byte counter */                        \
    src[i--] = 0x00;                     /* terminate string */                                     \
                                                                                                \
do {                                                                                            \
     /* fill in array from right to left */                                                     \
    src[i--] = number & 1 ? ONE : ZERO;                                                         \
    number >>= 1;   /* shift right 1 bit */                                                     \
 } while (number > 0);                                                                          \
  while (i >= 0) src[i--] = ZERO;  /* fill with ZERO */                                         \
  return src;                                                           
  BINSTR_BODY_DEFINITION
}

inline char* binstr(long int number) {
  BINSTR_BODY_DEFINITION
}
inline char* binstr(int number) {
  BINSTR_BODY_DEFINITION
}
inline char* binstr(short number) {
  BINSTR_BODY_DEFINITION
# undef BINSTR_BODY_DEFINITION
}

int main()
{
    long int val = 1;
    do { 
        // experimenting with different casts will produce different output lengths
        printf("%ld=\t\t%#lx=\t 0b%s\n", val, val, binstr(long long( val )));
        val *= 11;  // generate test data
    } while (val < 100000000);
  return 0;
}

prints out the following:

1 =    0x1 =   0b0000000000000000000000000000000000000000000000000000000000000001
11 =   0xb =   0b0000000000000000000000000000000000000000000000000000000000001011
121 =  0x79 =  0b0000000000000000000000000000000000000000000000000000000001111001
1331 = 0x533 = 0b0000000000000000000000000000000000000000000000000000010100110011

etc...

Upvotes: 0

Piotr Lenarczyk
Piotr Lenarczyk

Reputation: 11

Found somewhere on Internet:

void printBits( void const * const ptr, size_t const size )
{   printf( "hexVal = %#08x; decVal = %i \n", * ( uint* )ptr, * ( uint* )ptr );
    unsigned char *b = ( unsigned char* ) ptr;
    unsigned char byte;
    int i, j;
    for (i=size-1;i>=0;i--)
       for (j=7;j>=0;j--)
        {   byte = (b[i] >> j) & 1;
            printf( " %u ", byte );
        }
    puts("");
    for( int ind  = 31; ind > 9; ind-- )
        printf( "%d ", ind );
    for( int ind  = 9; ind > -1; ind-- )
        printf( " %d ", ind );      
    puts(""); puts("");
};

void compareValsBits( const void * ptrA, size_t sizeA, const void * ptrB, size_t sizeB )
{   if ( sizeA != sizeB ) return;
    printf( "comparing: \n[%#08x](%i)\n[%#08x](%i)\n====\n", * ( uint* )ptrA, * ( uint* )ptrA, * ( uint* )ptrB, * ( uint* )ptrB );
    unsigned char *a = ( unsigned char* ) ptrA;
    unsigned char *b = ( unsigned char* ) ptrB;
    unsigned char byteA, byteB;
    int i, j;

    for (i=sizeA-1;i>=0;i--)
        for (j=7;j>=0;j--)
        {   byteA = (a[i] >> j) & 1;
            printf( " %u ", byteA );
        }
    puts("");
    for (i=sizeA-1;i>=0;i--)
        for (j=7;j>=0;j--)
        {   byteB = (b[i] >> j) & 1;
            printf( " %u ", byteB );
        }
    puts("");
    for( int ind  = 31; ind > 9; ind-- )
        printf( "%d ", ind );
    for( int ind  = 9; ind > -1; ind-- )
        printf( " %d ", ind );      
    puts(""); 

    for (i=sizeA-1;i>=0;i--)
        for (j=7;j>=0;j--)
        {   byteA = (a[i] >> j) & 1;
            byteB = (b[i] >> j) & 1;
            if ( byteA == byteB )
                printf( "   " );
            else
                printf( " x " );
        }   
    printf( "\n====\n" );
};

Some trivial macro unrolling for setting, and resetting bits: https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros

#include <stdio.h>
typedef __uint32_t uint;
//==============================================================================================
#define STRINGIZE(arg)                  #arg
#define CONCATENATE(arg1, arg2)             arg1##arg2
#define FOR_EACH_1(macroName, param, x, ...)        macroName(param, x)
#define FOR_EACH_2(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_1(macroName, param,  __VA_ARGS__);
#define FOR_EACH_3(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_2(macroName, param,  __VA_ARGS__);
#define FOR_EACH_4(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_3(macroName, param,  __VA_ARGS__);
#define FOR_EACH_5(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_4(macroName, param,  __VA_ARGS__);
#define FOR_EACH_6(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_5(macroName, param,  __VA_ARGS__);
#define FOR_EACH_7(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_6(macroName, param,  __VA_ARGS__);
#define FOR_EACH_8(macroName, param, x, ...)        macroName(param, x);    FOR_EACH_7(macroName, param,  __VA_ARGS__);
#define FOR_EACH_NARG(...)              FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...)                 FOR_EACH_ARG_N(__VA_ARGS__) 
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N 
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FOR_EACH_(N, macroName, param, x, ...)      CONCATENATE(FOR_EACH_, N)(macroName, param, x, __VA_ARGS__)
#define FOR_EACH(macroName, param, x, ...)      FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), macroName, param, x, __VA_ARGS__)
//============================================================================================
//--------------------------------------------------------------------------------------------
//------------------------  MACRO KERNELS ----------------------------------------------------
//--------------------------------------------------------------------------------------------
#define SET_BIT( VARIABLE, bitNo )      { VARIABLE = ( ( ( VARIABLE >> bitNo ) & 0x1u ) != 0x1u )   \
                    ? VARIABLE |= 0x1u << bitNo                     \
                    : VARIABLE = VARIABLE;                      \
                    }
#define RESET_BIT( VARIABLE, bitNo )    { VARIABLE = ( ( ( VARIABLE >> bitNo ) & 0x1u ) != 0x0u )   \
                    ? VARIABLE &= ~( 0x1u << bitNo )                \
                    : VARIABLE = VARIABLE;                      \
                    }
#define BIT_VAL( VARIABLE, bitNo ) ( VARIABLE >> bitNo ) & 0x1u
//--------------------------------------------------------------------------------------------
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
uint a = 0x0u;
int main( void )
{   FOR_EACH( SET_BIT, a, 0, 1, 2 );
    printf( "0x%.8X\n", a );
    FOR_EACH( RESET_BIT, a, 1, 2 );
    printf( "0x%.8X\n", a );
    return 0;
};//end of main()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Upvotes: 0

Abhijit Sahu
Abhijit Sahu

Reputation: 325

#include<stdio.h>

int countOne =0;
int countZero =0;

void print_bits(int n,unsigned int num)
{
   if(n == 31) return;
   print_bits(n+1,num);
   (num & (1<<n)) ? printf("1"):printf("0");    
}

void countBits(int n,unsigned int num)
{
    if(n == 31) return;

    countBits(n+1,num);
    if(num & (1<<n))
    {
       countOne++;
    }
   else
   {
      if(countOne)
         countZero++;
   }
}

void printbits(int num)
{
    printf("%d : ",num);
    print_bits(-1,num); 
    printf("\n");
    countBits(-1,num);
    printf("\n");
}

int main()
{
    printbits(189);
    printf("NumberOf1's[%d] Numberof0's[%d]\n",countOne,countZero);
}

Upvotes: -2

Junius L
Junius L

Reputation: 16152

I have re-written the code from Is there a printf converter to print in binary format?

void    print_bits(unsigned char octet)
{
    int z = 128, oct = octet;

    while (z > 0)
    {
        if (oct & z)
            write(1, "1", 1);
        else
            write(1, "0", 1);
        z >>= 1;
    }
}

Upvotes: 4

David C. Rankin
David C. Rankin

Reputation: 84642

Including limits.h for CHAR_BIT, allows you to generalize the funciton to allow passing values of any length but limiting the the output to the number of bytes desired. Passing the file descriptor will allow writing to any open descriptor (or simply passing STDOUT_FILENO to write to stdout.

void writebits (const unsigned long v, int fd)
{
    if (!v)  { putchar ('0'); return; };

    size_t sz = sizeof v * CHAR_BIT;
    unsigned long rem = 0;

    while (sz--)
        if ((rem = v >> sz))
            write (fd, (rem & 1) ? "1" : "0", 1);
}

For example:

#include <stdio.h>
#include <unistd.h>

/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT  8
#endif

void writebits (const unsigned long v, int fd)
{
    if (!v)  { putchar ('0'); return; };

    size_t sz = sizeof v * CHAR_BIT;
    unsigned long rem = 0;

    while (sz--)
        if ((rem = v >> sz))
            write (fd, (rem & 1) ? "1" : "0", 1);
}

int main (void) {

    unsigned v = 0xcafebabe;

    writebits (v, STDOUT_FILENO);
    putchar ('\n');
    writebits ((unsigned char)(v >> 24), STDOUT_FILENO);
    putchar ('\n');

    return 0;
}

Example Output

$ ./bin/writebits
11001010111111101011101010111110
11001010

Upvotes: 1

Related Questions