I don't do this well myself, but with some side projects I've gone towards something like this.
Code:
/*******************************************************************************
* @Description
* This module defines miscellaneous utility functions.
*/
#include <limits.h>
#include <stddef.h>
/**
* Build information for this source file, embedded in the object code.
*/
static const char Build[] = __FILE__ ": " __DATE__ ", " __TIME__;
/**
* Writes the binary representation of an unsigned char value into the
* destination string.
* @param dest pointer to the destination string
* @param value the unsigned char value
* @return pointer to the destination string
*/
char *bits_uchar(char *dest, unsigned char value)
{
char *start = dest;
unsigned char bit;
for ( bit = 1 << (CHAR_BIT - 1); bit > 0; bit >>= 1 )
{
*dest++ = value & bit ? '1' : '0';
}
*dest = 0;
return start;
}
/**
* Writes the binary representation of an unsigned short value into the
* destination string.
* @param dest pointer to the destination string
* @param value the unsigned short value
* @return pointer to the destination string
*/
char *bits_ushort(char *dest, unsigned short value)
{
char *start = dest;
unsigned short bit;
for ( bit = (((unsigned short)-1) >> 1) + 1; bit > 0; bit >>= 1 )
{
*dest++ = value & bit ? '1' : '0';
}
*dest = 0;
return start;
}
/**
* Writes the binary representation of an unsigned int value into the
* destination string.
* @param dest pointer to the destination string
* @param value the unsigned int value
* @return pointer to the destination string
*/
char *bits_uint(char *dest, unsigned int value)
{
char *start = dest;
unsigned int bit;
for ( bit = (-1U >> 1) + 1; bit > 0; bit >>= 1 )
{
*dest++ = value & bit ? '1' : '0';
}
*dest = 0;
return start;
}
/**
* Writes the binary representation of an unsigned long value into the
* destination string.
* @param dest pointer to the destination string
* @param value the unsigned long value
* @return pointer to the destination string
*/
char *bits_ulong(char *dest, unsigned long value)
{
char *start = dest;
unsigned long bit;
for ( bit = ULONG_MAX / 2 + 1; bit > 0; bit >>= 1 )
{
*dest++ = value & bit ? '1' : '0';
}
*dest = 0;
return start;
}
/**
* Writes the binary representation of an object value into the destination
* string. Hyphens separate individual bytes.
* @param dest pointer to the destination string
* @param object pointer to an object
* @param size the size (in bytes) of the object
* @return pointer to the destination string
* @see bits_uchar
*/
char *bits_block(char *dest, const void *object, size_t size)
{
char *start = dest;
const unsigned char *byte;
for ( byte = object; size-- > 0; ++byte )
{
bits_uchar(dest, *byte);
dest += CHAR_BIT;
*dest++ = size > 0 ? '-' : 0;
}
return start;
}
#ifdef TEST_BITS /* module test driver */
#include <stdio.h>
int main(void)
{
char result[80];
unsigned char uc = 0x5A;
unsigned short uh = 0x1234;
unsigned int ui = 0xABCD;
unsigned long ul = 0xDEADBEEF;
double d = 123.456;
puts(Build);
printf("0x%-8X = \"%s\"\n", uc, bits_uchar (result, uc) );
printf("0x%-8hX = \"%s\"\n", uh, bits_ushort (result, uh) );
printf("0x%-8X = \"%s\"\n", ui, bits_uint (result, ui) );
printf("0x%-8lX = \"%s\"\n", ul, bits_ulong (result, ul) );
printf("0x%-8lX = \"%s\"\n", ul, bits_block(result, &ul, sizeof ul) );
printf("%-10g = \"%s\"\n", d, bits_block(result, &d, sizeof d) );
return 0;
}
/* my output
0x5A = "01011010"
0x1234 = "0001001000110100"
0xABCD = "00000000000000001010101111001101"
0xDEADBEEF = "11011110101011011011111011101111"
0xDEADBEEF = "11101111-10111110-10101101-11011110"
123.456 = "01110111-10111110-10011111-00011010-00101111-11011101-01011110-01000000"
*/
#endif /* TEST_BITS */
The attempt is that you can take the code in this module, make a separate project, define a macro, and have standalone testing of the code in it. Or something to that affect.
It's probably a screwed-up variant of "what you should be doing" that I've seen before.