Printing bits of a byte in C

Printing the bit representation of a byte is a very simple and interesting problem. There are numerous ways this can be done in many different programming languages out there. In C, one would do something like this for signed integers:


void print_bits(int num)
{
size_t bits = sizeof(num) * 8;
int max = 1 << (bits – 1);
int i;
for (i = 0; i < bits; i++) {
printf("%u", (num & max) ? 1 : 0);
num = num << 1;
}
printf("\n");
}

What exactly is this function doing?

Most of the code is pretty obvious. The key portions of the code are in lines 3 and 9.

Line 3, calculates the maximum possible positive value for the given type. In the example above, the given type is an int, and on my machine running GNU/Linux(x86_64),  the number of bits in an int is 32 and its maximum possible positive value for 2147483648.

The binary representation(shown in 4 chunks of 8 bits) of 1 on a 32 bit machine is:

00000000 00000000 00000000 00000001

which when left-shifted 31 times(line 3 in the above code), becomes(notice how the digit 1 has moved from being the LSB to being the MSB):

10000000 00000000 00000000 00000000

whose decimal value is 2147483648.

Having got the max value, we then bitwise-and(&) it with the give number(represented by num) and check the result(line 8). The bitwise-and will yield a number greater than 0, if there is a 1 in the MSB and will yield a 0 otherwise. Based on the result of this operation, we either print a 1 or a 0.

In each iteration, we left-shift  the given number by 1 bit(line 9). We continue to iterate until we’ve traversed all bits.

We can modify the function print_bits() to print the output in a much more readable fashion:


#include <stdint.h>
#include <limits.h>
#define numbits(x) (sizeof(x) * 8)
#define max_signed_value_of_type(t) \
(INTMAX_MAX >> (numbits(intmax_t) – numbits(t)))
void print_bits(int num)
{
size_t bits = numbits(num);
int max = max_signed_value_of_type(num) + 1;
int i;
for (i = 0; i < bits; i++) {
if (i && (i % 8) == 0)
printf(" ");
printf("%u", !!(num & max));
num = num << 1;
}
printf("\n");
}

We can also implement a function to count the number of 1’s and 0’s in the binary representation of a given number:


#include <stdint.h>
#include <limits.h>
#define numbits(x) (sizeof(x) * 8)
#define max_signed_value_of_type(t) \
(INTMAX_MAX >> (numbits(intmax_t) – numbits(t)))
void count_bits(unsigned int num)
{
size_t bits = numbits(num);
unsigned int max = max_signed_value_of_type(num) + 1;
int i;
unsigned int t = num;
int zeroes = 0, ones = 0;
for (i = 0; i < bits; i++) {
if (!!(num & max))
ones++;
else
zeroes++;
num = num << 1;
}
printf("%u has %d 0's and %d 1's in its binary representation.\n", t, zeroes, ones);
}

view raw

count_bits.c

hosted with ❤ by GitHub

The count_bits() function above for input number 2 which in binary is 00000000 00000000 00000000 00000010 we get an output:

2 has 31 0’s and 1 1’s in its binary representation.

 

This post is a result of a discussion with my nephew who recently took to programming and I was trying to explain bits and bytes to him. Although C is probably not the right language when introducing a high-schooler to programming, I thought it is the language that expresses bits and bytes well, and also, it is the language that I know the best.

Updates on QNAP Finder for Linux

I have made a few fixes to the qnap-finder, and pushed those changes to qnap-finder repository on github. Visually, the only change that is seen is the access URL:

$ ./qnap-finder
1)
Hostname    : cher
IP Address  : 10.0.0.59
Type        : NAS(TS-410)TS-419ITS-410
URL         : https://10.0.0.59/cgi-bin/login.html

If run with ‘-h’ or ‘–help’, qnap-finder will now display a list of all available options.

$ ./qnap-finder -h
qnap-finder v0.1

Usage: qnap-finder [options]

options include:
–help|-h          This help text
–detail|-d        Query for detailed information.(default is brief)
–verbose|-v       Verbose debug
–version|-V       Prints current version

More updates, when I have them.

QNAP finder for Linux

I have a QNAP Turbo NAS TS410. And under a DHCP setup that is available where I live, it is difficult to figure out the IP address of my NAS box is every time I restart, since the router isn’t doing a great job with the DHCP leases. The QNAP Finder for Linux that QNAP provides has strict dependencies on a specific gtk+ version. The source isn’t available, making it impossible to use on my Arch Linux machine.

It got me wondering  though, what the app actually does. I installed the Windows version of it on a borrowed laptop and using wireshark, I figured a bunch of things, all of which I’ve documented here. With that information, I wrote a small command-line utility that will essentially do the job for me.  I call it qnap-finder and it is available on github.

A quick preview of what the tool shows when run:


$ ./qnap-finder
1)
Hostname    : blah
IP Address  : 10.0.0.30
Type           : NAS(TS-410)TS-419ITS-410

This is just the basic detail. There is a lot more information available, like the number of hard disks, the version of the firmware which I still haven’t got to parsing and displaying, will get that done soon. Hopefully someone else will find this useful. And it is quite possible that I haven’t done something right, so please feel free to contribute/fork or report bugs.

* Disclaimer
============
This program is a work in progress and isn't guaranteed to work with all QNAP devices.
Although this is meant to be a replacement for the Windows/Mac versions of QNAP finder,
it is not guaranteed to work that way.

K&RIP!

Dennis Ritchie passed away.

It is indeed a sad day.

I started using computers when in university (I was 18 then). And in the last 14 years, I have been using both C and Unix (and its variants, Linux mostly). And if I look around, most of the devices that I have, including but not limited to, my laptop, my phone, my desktop at work, use C and Unix (Linux in this case). I earn my 'daily-bread' as a C programmer, I have enjoyed being a C programmer. I just love the flexibility that it provides and its sheer simplicity. I've _always_ had a copy of The C programming language with me. And that is the book that I always keep going back to, between jobs (for interviews) and occasional reference.

I owe it to Dennis Ritchie big time.

My heartfelt condolences to his family and friends. May his soul rest in peace.