Behind the data types 'char', 'int', 'float' et al, are varying sizes of storage space. The 'bit' is the smallest data representation, and it is boolean; i.e., it is either '0' or '1'. 'False' or 'True'. 'Off' or 'On'. In this installment, we dig deep into the world of 'bits', 'nibbles' (groups of 4 'bits'), and 'bytes' (groups of 8 'bits' or 2 'nibbles').
/* pgm24 source */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_32_BIT_NUM 4294967295
#define MAX_POWER_OF_2_NUM 2147483648
enum handlenewlines {HEADINGYES, HEADINGNO, FALSE = -1, TRUE};
char *return_nibble(int);
void prnt_data(unsigned int, int);
void construct_32_bits_string(unsigned int, char *);
int cvrt_hexval_char_to_int(int);
int main(int argc, char *argv[]) {
int dobitpos;
unsigned int numval;
if ((argc == 2) && (strcmp(argv[1], "bitpos") == 0))
dobitpos = TRUE;
else if (argc == 1)
dobitpos = FALSE;
else {
printf("\n\nThis program only recognizes \"bitpos\" as a parameter.\n\n");
return(-1);
}
numval = 0;
printf("\n");
printf("'0' is a \"bit\" '0000' is a \"nibble\"\n");
printf("'0000 0000' is two nibbles, also called a \"byte\"\n");
printf("8 \"nibbles\" (or 4 \"bytes\") make a 32-bit value\n");
printf("This applies to 'int' - integer, but may differ by machine or OS\n\n");
if (dobitpos == FALSE) {
for (numval = 0; numval < 16; numval++)
prnt_data(numval, (numval == 0) ? HEADINGYES : HEADINGNO);
/* 4 arbitrary integer values, and a MAX category value */
prnt_data(3028912, HEADINGNO);
prnt_data(29901098, HEADINGNO);
prnt_data(782971823, HEADINGNO);
prnt_data(1982971823, HEADINGNO);
prnt_data(MAX_32_BIT_NUM, HEADINGNO);
}
else {
printf(" === Showing one BIT position ===\n");
prnt_data(1, HEADINGYES);
for (numval = 2; numval < MAX_POWER_OF_2_NUM; numval *= 2)
prnt_data(numval, HEADINGNO);
prnt_data(MAX_POWER_OF_2_NUM, HEADINGNO);
}
printf("\n");
return(0);
}
void prnt_data(unsigned int numval, int newline) {
char rbuffer[48];
if (newline == HEADINGYES)
printf("MSB LSB = Number\n");
construct_32_bits_string(numval, rbuffer);
printf("%s %-16u\n", rbuffer, numval);
}
void construct_32_bits_string(unsigned int val, char *result_string) {
char all_nibbles[9];
char rn7[5]; char rn6[5]; char rn5[5]; char rn4[5];
char rn3[5]; char rn2[5]; char rn1[5]; char rn0[5];
int n7; int n6; int n5; int n4;
int n3; int n2; int n1; int n0;
snprintf(all_nibbles, 9, "%08x", val);
n7 = cvrt_hexval_char_to_int(all_nibbles[0]);
n6 = cvrt_hexval_char_to_int(all_nibbles[1]);
n5 = cvrt_hexval_char_to_int(all_nibbles[2]);
n4 = cvrt_hexval_char_to_int(all_nibbles[3]);
n3 = cvrt_hexval_char_to_int(all_nibbles[4]);
n2 = cvrt_hexval_char_to_int(all_nibbles[5]);
n1 = cvrt_hexval_char_to_int(all_nibbles[6]);
n0 = cvrt_hexval_char_to_int(all_nibbles[7]);
strcpy(rn0, return_nibble(n0)); strcpy(rn1, return_nibble(n1));
strcpy(rn2, return_nibble(n2)); strcpy(rn3, return_nibble(n3));
strcpy(rn4, return_nibble(n4)); strcpy(rn5, return_nibble(n5));
strcpy(rn6, return_nibble(n6)); strcpy(rn7, return_nibble(n7));
snprintf(result_string, 48, "%s %s %s %s %s %s %s %s", rn7, rn6, rn5, rn4, rn3, rn2, rn1, rn0);
}
char *return_nibble(int nibble_value) {
static char *bytestrs[17] = {
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111",
"UNKN"
};
return(bytestrs[nibble_value]);
}
/* decimal 48 - 57 translates to character '0' to '9' */
/* decimal 97 - 102 translates to character 'a' to 'f' */
/* thus, if 'achar' is a digit CHARACTER, achar - 48 */
/* translates to NUMERIC 0 to 9 */
/* if 'achar' is NOT a digit CHARACTER, achar - 87 */
/* translates to NUMERIC 10 to 15 */
/* we end up with chars '0' - 'f' translated to ints 0 - 15 */
int cvrt_hexval_char_to_int(int achar) {
int retval;
retval = (isdigit(achar) != 0) ? achar - 48 : achar - 87;
if ((retval >= 0) && (retval < 16))
return(retval);
else {
printf("\n\nUnexpected error.\n\n");
return(-1);
}
}