Comparing unsigned char bits.


/******************************************************************************/
/* Printing an unsigned character in bits                                       */

#include    <stdio.h>

void display_bits ( unsigned char );

int main()
{
    unsigned char x;                          /* Number to be printed in bits  */

    printf ( "Enter an unsigned character: " );
    scanf ( "%c", &x );
    display_bits ( x );
}

void display_bits ( unsigned char value )
{
    unsigned char i,
                 display_mask = 1 << ( 8 * sizeof(unsigned char) - 1 );
printf("%c\n",display_mask);
    /* The display_mask contains 1 shifted by the number of bits in int       */

    printf ( "%7c = ", value );

    for ( i = 1; i <= ( 8 * sizeof(unsigned char)); i++ )
    {
        putchar ( ( value & display_mask ) ? '1' : '0' );
        value <<= 1;

        if ( !( i % 8 ) )
            putchar ( ' ' );
    }

    putchar ( '\n' );
}

The output here is not what I am expecting. I want the input to be displayed in binary.

What exactly is not what you are expecting ? Your program output is displayed in binary and the values looks correct to me.

There are minor things that can be improved, like:

  • computing sizeof(unsigned char) which is pointless as it is always 1 by the standard.
  • printf("%c\n",display_mask); doesn't print anything useful as ASCII character 128 is non printable.
  • printf ( "%7c = ", value ); %7c should be just %c as you aren't using wide (multibyte) characters.

If I enter 9, the output is

Enter an unsigned character: 9
?
9 = 00111001

So, the question mark is because 128 is too big for 1 byte and I am not expecting 00111001 because that is 2^5 + 2^4 + 2^3 + 1.

No, bytes are from 0 to 255. The question mark is there because ASCII character 128 is non printable.

Well, 00111001 is precisely the binary representation of the '9' character. What are you expecting instead ?

00001001

---------- Post updated at 03:34 PM ---------- Previous update was at 03:30 PM ----------

How could I translate each binary position in an unsigned char to a corresponding number 1 - 8?

Numbers already are bits, so you can just use the bit shift operator.

# Get bit
int bit=3; // bit from 0 to 31
unsigned int bitval=(1<<bit);

printf("Value of bit %u is %u\n", bit, bitval);

And do binary math to see when they're set.

unsigned char value=255;
int bit=3;
unsigned char bitset=value & (1<<bit);

if(bitset) { printf("bit %d set\n", bit+1); }
else       { printf("bit %d unset\n", bit+1); }

Then read the "9" as a number instead of as a character...

scanf("%u", &x);

Or read it as a char and extract out the the number by subtracting '0' from it...

scanf("%c", &x);
x = x - '0';

This isn't making sense to me. What is a good book or site that explains this?

Here is the book: The C Programming Language

I'm not sure we're using the same terms on either side of the equation, so we may be answering the wrong questions. Could you explain what you want in more detail please?


#include <stdio.h>
int main()
{
    unsigned char a,b;
    a = 1 + 2 + 4 + 16 + 32 + 64 + 128;
    b=1;

    while(b<=128)
    {
        if(a & b)
            printf("%d\n", b);

        if(b == 128)
            b = b + 1;
        else
            b = b * 2;
    }
}

I'm using something like this code to mark each bit position with one of the powers of two and then comparing the byte with a combination of each power of two. Thanks for the help. I'm probably not very clear about what I'm talking about.

I still don't quite get what you want, no. Why would you want to 'mark' bit positions? You already know where they are, and can't even mark anywhere else.

Whatever it is, you can probably do it with bit shift.

int n;

printf("bit shift\n");
for(n=0; n<=7; n++) printf("1 << %d = %d\n", n, 1<<n);

In your original post, 0011 1001, is binary for 0x39 which is the ASCII value for 9; Shamrock hit the nail on the head -- you're reading from stdin and need to convert the ASCII into an iteger before you can treat it as such.

I think this does what you want: reads a number from stdin (doesn't do much error checking) then prints the bits.

#include "stdio.h"
#include "stdlib.h"

void show_bits( unsigned char byte )
{
    int i;

    printf( "%d =", (unsigned int) byte );
    for( i = 0; i <  8; i++ )                   // for each bit
    {
        printf( "%d", byte & 0x80 ? 1 : 0 );    // test the high order (left) bit and print 1 if on
        byte <<= 1;                             // shift to the left 1 bit
    }
    printf( "\n" );                             // final newline
}

int main( int argc, char **argv )
{
    unsigned int    value;

    printf( "enter non-number or ctl-D to quit\n" );
    for( ; ; )
    {
        printf( "enter a number (0-255): " );
        if(  scanf( "%u", &value ) <= 0 )      // read value converting it to unsigned
        {
            printf( "\n" );
            exit( 0 );
        }
        if( value < 256 )
            show_bits( (unsigned char ) value  );   // typecast not necessary, but shows intent
        else
            printf( "%d is out of range for a byte\n", value );
    }
}

return 0;

I am trying to use a bit vector to determine if a number generated by rand()%8 has been generated yet. I'll mess with it some more in a bit. Thanks.

Here is a quick example of setting and checking a bit vector based on 255 possible combinations:

#include "stdio.h"
#include "stdlib.h"

#define VSIZE  256/8            // vector size in bytes
void mark( unsigned char *vector, unsigned char byte )
{
    int idx;
    int mask;

    idx = byte / 8;
    mask = 1 << (byte % 8);

    vector[idx] |= mask;
}

int check( unsigned char *vector, unsigned char byte )
{
    int idx;
    int mask;

    idx = byte / 8;
    mask = 1 << (byte % 8);

    return vector[idx] & mask;
}

int main( int argc, char **argv )
{
    unsigned int    value;
    unsigned char vector[VSIZE];

    printf( "enter non-number or ctl-D to quit\n" );
    for( ; ; )
    {
        printf( "enter a number (0-255): " );
        if( scanf( "%u", &value ) <= 0 )        // read value converting it to unsigned
        {
            printf( "\n" );
            exit( 0 );
        }
        if( value < 256 )
        {
            printf( "the value %u has %sbeen entered before\n", value, check( vector, value ) ? "" : "not " );
            mark( vector, value );
        }
        else
            printf( "%d is out of range for a byte\n", value );
    }

    return 0;
}

In that case you'll also want |=, to set bits.

int v=0;
v |= (1<<3); // Set fourth bit

You can also clear bits, by anding the opposite.

int v=255;
v &= ~(1<<3); // turn off fourth bit