Reputation: 16152
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;
}
}
}
Upvotes: 2
Views: 20306
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
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
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
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
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