print out ascii characters

Y

Yoshi

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....

#include <stdio.h>
#include <ctype.h>

int main(void)
{
unsigned int c,j;
unsigned char k;
unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
void *s=(void*)buf;

for(c=0;c<=255;c++){
memset(s,0,sizeof(buf));
for(j=1,k=7;j<=256;j=j*2,k--){
if(c&j)
buf[k]='1';
else
buf[k]='0';
}
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
}
return 0;
}


Thank you
 
N

Nick

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....

#include <stdio.h>
#include <ctype.h>

int main(void)
{
unsigned int c,j;
unsigned char k;
unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
void *s=(void*)buf;

for(c=0;c<=255;c++){
memset(s,0,sizeof(buf));
for(j=1,k=7;j<=256;j=j*2,k--){
if(c&j)
buf[k]='1';
else
buf[k]='0';
}
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
}
return 0;
}

An aside on the question: you're not going to print ASCII with that,
you're going to print whatever is the code on your computer (which is
very likely (but not guaranteed - a few of us here have used EBCDIC
machines)) to be ASCII for part of the range, but you'll almost
certainly have some printable characters above 127 (where ASCII stops)
that will be displayed, and these are very likely to vary from operating
system to operating system (or even environments within a single OS on a
single physical machine).

That aside, I'm afraid the answer is no - there's no way to print a
value as binary in standard C. A lot of people have added a %b or
similar to printf but it's an extension and not always available. There
are lots of ways to convert to a binary representation and yours is as
good as anything. I'd be tempted to put it in a function - to make the
purpose of the loop (printing the values) more obvious.
 
B

Barry Schwarz

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....

#include <stdio.h>
#include <ctype.h>

int main(void)
{
unsigned int c,j;
unsigned char k;
unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};

The initialization is useless since it is completely overwritten by
the memset below. In particular, the '\n' is lost. Which is actually
desirable since you want buf[8] to be 0 anyway.
void *s=(void*)buf;

for(c=0;c<=255;c++){
memset(s,0,sizeof(buf));

Why bother with s when
memset(buf, 0, sizeof buf);
does the job just as well?

On the other hand, why bother at all since you replace all the values
except buf[8] with '0' or '1' below. Your best approach would be to
replace the initialization of buf with {0} and remove this.
for(j=1,k=7;j<=256;j=j*2,k--){

On the first iteration, k=7, j=1.
Next k=6, j=2.
Next k=5, j=4.
Next k=4, j=8.
Next k=3, j=16.
Next k=2, j=32.
Next k=1, j=64.
Next k=0, j=128.
Next k=255, j=256 and your code below invokes
undefined behavior by attempting to access buf[255]. You are looping
one to many times.
if(c&j)
buf[k]='1';
else
buf[k]='0';
}
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);

Don't you think a little horizontal white space would make this a lot
more readable?
 
B

bartc

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
for(j=1,k=7;j<=256;j=j*2,k--){
if(c&j)
buf[k]='1';
else
buf[k]='0';
}

It's difficult to avoid using a loop. But you can put the code into a
function. As in the the following example, which converts an int value into
a string of "0"s and "1"s (and is always a fixed length, typically 32
characters):

#include <stdio.h>
#include <limits.h>

/* Convert value a into a string of zeros and ones at dest */

void str_bin(char *dest,int a) {
int n = sizeof(a)*CHAR_BIT;
int mask = 1;

dest[n]=0;
while (mask) {
dest[--n] = (a & mask ?'1':'0');
mask <<=1;
}
}

/* Usage: */

int main(void)
{
char str[100]; /* 33 or 65 at least */
int i=16385;

str_bin(str, i);
printf("Binary(%d) = %s\n",i,str);
}
 
Y

Yoshi

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
#include <stdio.h>
#include <ctype.h>
int main(void)
{
    unsigned int c,j;
    unsigned char k;
    unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
    void *s=(void*)buf;
    for(c=0;c<=255;c++){
        memset(s,0,sizeof(buf));
        for(j=1,k=7;j<=256;j=j*2,k--){
            if(c&j)
                buf[k]='1';
            else
                buf[k]='0';
        }
        printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
    }
   return 0;
}

An aside on the question: you're not going to print ASCII with that,
you're going to print whatever is the code on your computer (which is
very likely (but not guaranteed - a few of us here have used EBCDIC
machines)) to be ASCII for part of the range, but you'll almost
certainly have some printable characters above 127 (where ASCII stops)
that will be displayed, and these are very likely to vary from operating
system to operating system (or even environments within a single OS on a
single physical machine).

Yes, I was wrong about the range of ASCII characters. and did not know
that
the range of ASCII varies from OS to OS...

That aside, I'm afraid the answer is no - there's no way to print a
value as binary in standard C.  A lot of people have added a %b or
similar to printf but it's an extension and not always available.  There
are lots of ways to convert to a binary representation and yours is as
good as anything.  I'd be tempted to put it in a function - to make the
purpose of the loop (printing the values) more obvious.

I see, I just wondered that if there exists some to do that, but good
to
know that I can't, Thanks.
 
L

Lew Pitcher

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
[snip]

An aside on the question: you're not going to print ASCII with that,
you're going to print whatever is the code on your computer (which is
very likely (but not guaranteed - a few of us here have used EBCDIC
machines)) to be ASCII for part of the range, but you'll almost
certainly have some printable characters above 127 (where ASCII stops)
that will be displayed, and these are very likely to vary from operating
system to operating system (or even environments within a single OS on a
single physical machine).

Yes, I was wrong about the range of ASCII characters. and did not know
that the range of ASCII varies from OS to OS...

No, it doesn't.

ASCII extends from 0x00 to 0x7f, regardless of operating system. /If/ you
wish to interpret values beyond 0x7f as characters, you must use some other
characterset other than ASCII.


[snip]
 
Y

Yoshi

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
#include <stdio.h>
#include <ctype.h>
int main(void)
{
   unsigned int c,j;
   unsigned char k;
   unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};

The initialization is useless since it is completely overwritten by
the memset below.  In particular, the '\n' is lost.  Which is actually
desirable since you want buf[8] to be 0 anyway.
   void *s=(void*)buf;
   for(c=0;c<=255;c++){
       memset(s,0,sizeof(buf));

Why bother with s when
    memset(buf, 0, sizeof buf);
does the job just as well?

On the other hand, why bother at all since you replace all the values
except buf[8] with '0' or '1' below.  Your best approach  would be to
replace the initialization of buf with {0} and remove this.
       for(j=1,k=7;j<=256;j=j*2,k--){

On the first iteration, k=7, j=1.
Next                        k=6, j=2.
Next                        k=5, j=4.
Next                        k=4, j=8.
Next                        k=3, j=16.
Next                        k=2, j=32.
Next                        k=1, j=64.
Next                        k=0, j=128.
Next                        k=255, j=256 and your code below invokes
undefined behavior by attempting to access buf[255].  You are looping
one to many times.

Thanks, now i see a lot bugs in my code.
           if(c&j)
               buf[k]='1';
           else
               buf[k]='0';
       }
       printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);

Don't you think a little horizontal white space would make this a lot
more readable?
   }
   return 0;
}
Thank you
 
Y

Yoshi

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
#include <stdio.h>
#include <ctype.h>
int main(void)
{
    unsigned int c,j;
    unsigned char k;
    unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
    void *s=(void*)buf;
    for(c=0;c<=255;c++){
        memset(s,0,sizeof(buf));
        for(j=1,k=7;j<=256;j=j*2,k--){
            if(c&j)
                buf[k]='1';
            else
                buf[k]='0';
        }
        printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
    }
   return 0;
}

I would write that, this way:

#include <stdio.h>
#include <ctype.h>
#include <limits.h>

void bit_str(char *s1, const void *s2, size_t n);

int main(void)
{
     unsigned char c = 0;
     char buf[sizeof c * CHAR_BIT + 1];

     do {
         bit_str(buf, &c, sizeof c);
         printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s\n",
             isprint(c) ? c : '.' , c, c, c, buf);
     } while (c++ != (unsigned)UCHAR_MAX);
     return 0;

}

void bit_str(char *s1, const void *s2, size_t n)
{
     const unsigned char *const byte = s2;

Thanks, but I don't see why it's not like...
const unsigned char *byte = s2;

Could you explain why you used below?
const unsigned char *const byte = s2;

     while (n-- != 0) {
         unsigned mask = ((unsigned char)-1 >> 1) + 1;

         do {
             *s1++ = (char)(mask & byte[n] ? '1' : '0');
             mask >>= 1;
         } while (mask != 0);
     }
     *s1 = '\0';

}
 
Y

Yoshi

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
       for(j=1,k=7;j<=256;j=j*2,k--){
           if(c&j)
               buf[k]='1';
           else
               buf[k]='0';
       }

It's difficult to avoid using a loop. But you can put the code into a
function. As in the the following example, which converts an int value into
a string of "0"s and "1"s (and is always a fixed length, typically 32
characters):

#include <stdio.h>
#include <limits.h>

/* Convert value a into a string of zeros and ones at dest */

void str_bin(char *dest,int a) {
 int n = sizeof(a)*CHAR_BIT;
 int mask = 1;

 dest[n]=0;
 while (mask) {
  dest[--n] = (a & mask ?'1':'0');
  mask <<=1;
 }

}

/* Usage: */

int main(void)
{
 char str[100]; /* 33 or 65 at least */
 int i=16385;

 str_bin(str, i);
 printf("Binary(%d) = %s\n",i,str);

}

Thanks, now I see there is no way to waive loop to print out the
contents of data in binary format...
 
B

bartc

Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out
binary data like "00100001". Now I'm using loop, but it looks
ugly.... for(j=1,k=7;j<=256;j=j*2,k--){
while (mask) {
dest[--n] = (a & mask ?'1':'0');
mask <<=1;
}
Thanks, now I see there is no way to waive loop to print out the
contents of data in binary format...

If you just want to print (8-bit) char values, then you can just have an
array of 256 strings:

char *table[256] = {"00000000","00000001",..."11111111"};

then use an array to convert:

printf("%s",table[123]);

To convert integers, you can still use the same table, using 4 (or 8)
successive strings from the table, without using a loop.

But this will all take extra space (and lots of typing), while having a loop
is not really a big deal.
 
B

Ben Bacarisse

Yoshi said:
Thanks, but I don't see why it's not like...
const unsigned char *byte = s2;

Could you explain why you used below?
const unsigned char *const byte = s2;

The second const is a promise that 'byte' will not be changed. The
code has the same effect without it but the const gives more
information.

<snip>
 
B

Ben Bacarisse

bartc said:
Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out
binary data like "00100001". Now I'm using loop, but it looks
ugly.... for(j=1,k=7;j<=256;j=j*2,k--){
while (mask) {
dest[--n] = (a & mask ?'1':'0');
mask <<=1;
}
Thanks, now I see there is no way to waive loop to print out the
contents of data in binary format...

If you just want to print (8-bit) char values, then you can just have
an array of 256 strings:

char *table[256] = {"00000000","00000001",..."11111111"};

....or a table of unsigned longs:

unsigned long table[256] = { 0x0, 0x1, ... 0x11111111 };
then use an array to convert:

printf("%s",table[123]);

....with printf("%08lx", table[123]);

I think a good compromise between table size and looping is to use
unsigned shorts from 0 to 0x1111 and to print 4 bits at a time.

<snip>
 
Y

Yoshi

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....
[snip]
An aside on the question: you're not going to print ASCII with that,
you're going to print whatever is the code on your computer (which is
very likely (but not guaranteed - a few of us here have used EBCDIC
machines)) to be ASCII for part of the range, but you'll almost
certainly have some printable characters above 127 (where ASCII stops)
that will be displayed, and these are very likely to vary from operating
system to operating system (or even environments within a single OS on a
single physical machine).
Yes, I was wrong about the range of ASCII characters. and did not know
that the range of ASCII varies from OS to OS...

No, it doesn't.

ASCII extends from 0x00 to 0x7f, regardless of operating system. /If/ you
wish to interpret values beyond 0x7f as characters, you must use some other
characterset other than ASCII.
Oops, sorry, I should have read carefully.
 
Y

Yoshi

Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out binary
data like "00100001". Now I'm using loop, but it looks ugly....

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    unsigned int c,j;
    unsigned char k;
    unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
    void *s=(void*)buf;

    for(c=0;c<=255;c++){
        memset(s,0,sizeof(buf));
        for(j=1,k=7;j<=256;j=j*2,k--){
            if(c&j)
                buf[k]='1';
            else
                buf[k]='0';
        }
        printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
    }
        return 0;

}

Thank you

Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>

typedef union _mychar{
char c;
struct{
unsigned short seven: 1;
unsigned short six: 1;
unsigned short five: 1;
unsigned short four: 1;
unsigned short three: 1;
unsigned short two: 1;
unsigned short one: 1;
unsigned short zero: 1;
}bit;
}mychar;

int main(void)
{
mychar b;
unsigned int c;
unsigned char buf[CHAR_BIT];

for(c=0;c<=127;c++){
b.c = c;
buf[0] = (b.bit.zero) ?'1':'0';
buf[1] = (b.bit.one ) ?'1':'0';
buf[2] = (b.bit.two ) ?'1':'0';
buf[3] = (b.bit.three) ?'1':'0';
buf[4] = (b.bit.four) ?'1':'0';
buf[5] = (b.bit.five) ?'1':'0';
buf[6] = (b.bit.six) ?'1':'0';
buf[7] = (b.bit.seven) ?'1':'0';

printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
isprint((int)c)?c:'.', c, c, c, buf);
}
return 0;
}
 
B

bartc

Yoshi said:
On Nov 19, 11:33 pm, Yoshi <[email protected]> wrote:
Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.
typedef union _mychar{
char c;
struct{
unsigned short seven: 1;
unsigned short six: 1;
unsigned short five: 1;
unsigned short four: 1;
unsigned short three: 1;
unsigned short two: 1;
unsigned short one: 1;
unsigned short zero: 1;
}bit;
}mychar;

int main(void)
{
mychar b;
unsigned int c;
unsigned char buf[CHAR_BIT];

for(c=0;c<=127;c++){
b.c = c;
buf[0] = (b.bit.zero) ?'1':'0';
buf[1] = (b.bit.one ) ?'1':'0';
buf[2] = (b.bit.two ) ?'1':'0';
buf[3] = (b.bit.three) ?'1':'0';
buf[4] = (b.bit.four) ?'1':'0';
buf[5] = (b.bit.five) ?'1':'0';
buf[6] = (b.bit.six) ?'1':'0';
buf[7] = (b.bit.seven) ?'1':'0';

You really don't like loops do you ... ?

Anyway you don't really need the union thing above:

buf[0]=(b & 0x80) ? '1' : '0';
buf[1]=(b & 0x40) ? '1' : '0';
....
And there are probably other ways of coding it.

BTW you should make buf a bit longer and set buf[8] to 0 (NUL), to make it a
proper string.
 
B

bartc

Ben said:
bartc said:
Yoshi said:
Hello, I'm trying to write a code to print out ascii characters,
and wondering if there is a more sophisticated way to print out
binary data like "00100001". Now I'm using loop, but it looks
ugly.... for(j=1,k=7;j<=256;j=j*2,k--){
while (mask) {
dest[--n] = (a & mask ?'1':'0');
mask <<=1;
}
Thanks, now I see there is no way to waive loop to print out the
contents of data in binary format...

If you just want to print (8-bit) char values, then you can just have
an array of 256 strings:

char *table[256] = {"00000000","00000001",..."11111111"};

...or a table of unsigned longs:

unsigned long table[256] = { 0x0, 0x1, ... 0x11111111 };

Yes, a nice bit of lateral thinking there.

Although, once you accept using an array to do this, you are still going to
use either 1K or 4K of extra storage. With the string table being more
versatile (in being able to other things with the strings), and possibly a
little faster.
I think a good compromise between table size and looping is to use
unsigned shorts from 0 to 0x1111 and to print 4 bits at a time.

I think the OP has already decided to use shorts from 0 to 1, and print one
bit at a time...
 
K

Keith Thompson

Yoshi said:
Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>

typedef union _mychar{
char c;
struct{
unsigned short seven: 1;
unsigned short six: 1;
unsigned short five: 1;
unsigned short four: 1;
unsigned short three: 1;
unsigned short two: 1;
unsigned short one: 1;
unsigned short zero: 1;
}bit;
}mychar;

Bit fields of types other than int, signed int, unsigned int, and (C99
only) _Bool are not portable, though they're a common extension.

What does unsigned short buy you here vs. unsigned int?

Why are there 8 fields in the struct? Are you assuming CHAR_BIT==8?
You loop over the range 0..127, which only requires 7 bits.
int main(void)
{
mychar b;
unsigned int c;
unsigned char buf[CHAR_BIT];

for(c=0;c<=127;c++){
b.c = c;
buf[0] = (b.bit.zero) ?'1':'0';
buf[1] = (b.bit.one ) ?'1':'0';
buf[2] = (b.bit.two ) ?'1':'0';
buf[3] = (b.bit.three) ?'1':'0';
buf[4] = (b.bit.four) ?'1':'0';
buf[5] = (b.bit.five) ?'1':'0';
buf[6] = (b.bit.six) ?'1':'0';
buf[7] = (b.bit.seven) ?'1':'0';

printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
isprint((int)c)?c:'.', c, c, c, buf);
}
return 0;
}

How do you know whether bit.zero corresponds to the high-order bit of
c or the low-order bit? (Hint: You don't.)
 
Y

Yoshi

Yoshi said:
Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.
typedef union _mychar{
    char c;
    struct{
    unsigned short seven: 1;
    unsigned short six:   1;
    unsigned short five:  1;
    unsigned short four:  1;
    unsigned short three: 1;
    unsigned short two:   1;
    unsigned short one:   1;
    unsigned short zero:  1;
    }bit;
}mychar;
int main(void)
{
    mychar b;
    unsigned int c;
    unsigned char buf[CHAR_BIT];
    for(c=0;c<=127;c++){
        b.c = c;
        buf[0] = (b.bit.zero)  ?'1':'0';
        buf[1] = (b.bit.one )  ?'1':'0';
        buf[2] = (b.bit.two )  ?'1':'0';
        buf[3] = (b.bit.three) ?'1':'0';
        buf[4] = (b.bit.four)  ?'1':'0';
        buf[5] = (b.bit.five)  ?'1':'0';
        buf[6] = (b.bit.six)   ?'1':'0';
        buf[7] = (b.bit.seven) ?'1':'0';

You really don't like loops do you ... ?
Ehh..I tried to waive loop and end up with hard coded loop....
Anyway you don't really need the union thing above:

          buf[0]=(b & 0x80) ? '1' : '0';
          buf[1]=(b & 0x40) ? '1' : '0';
...
And there are probably other ways of coding it.

BTW you should make buf a bit longer and set buf[8] to 0 (NUL), to make it a
proper string.
Yes, you're right, thanks.

[/QUOTE]
 
Y

Yoshi

[...]


Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
typedef union _mychar{
    char c;
    struct{
    unsigned short seven: 1;
    unsigned short six:   1;
    unsigned short five:  1;
    unsigned short four:  1;
    unsigned short three: 1;
    unsigned short two:   1;
    unsigned short one:   1;
    unsigned short zero:  1;
    }bit;
}mychar;

Bit fields of types other than int, signed int, unsigned int, and (C99
only) _Bool are not portable, though they're a common extension.

What does unsigned short buy you here vs. unsigned int?

First I tried bool, but it didn't work(now I see it's _Bool). Then I
tried unsigned short, and it worked for gcc on Linux. I thought it
would be better since unsigned short would only consume 2 bytes, but
int would be 4 bytes(not good thing to do though..)
I usually try and error when I code, but could you tell me where
should I refer to write a portable code? I cannot see which standard
document I should check because it looks so many standards exist.

Why are there 8 fields in the struct?  Are you assuming CHAR_BIT==8?
You loop over the range 0..127, which only requires 7 bits.
Yes, I was assuming 8 bits for char type, thank you.

int main(void)
{
    mychar b;
    unsigned int c;
    unsigned char buf[CHAR_BIT];
    for(c=0;c<=127;c++){
        b.c = c;
        buf[0] = (b.bit.zero)  ?'1':'0';
        buf[1] = (b.bit.one )  ?'1':'0';
        buf[2] = (b.bit.two )  ?'1':'0';
        buf[3] = (b.bit.three) ?'1':'0';
        buf[4] = (b.bit.four)  ?'1':'0';
        buf[5] = (b.bit.five)  ?'1':'0';
        buf[6] = (b.bit.six)   ?'1':'0';
        buf[7] = (b.bit.seven) ?'1':'0';
        printf("[%c]  decimal:%03d  octal:%03o  hex:%02x  bin:%s\n",
                    isprint((int)c)?c:'.', c, c, c, buf);
    }
   return 0;
}

How do you know whether bit.zero corresponds to the high-order bit of
c or the low-order bit?  (Hint: You don't.)

OK, thanks for telling me that, though I want to see the reference...
 
K

Keith Thompson

Yoshi said:
First I tried bool, but it didn't work(now I see it's _Bool). Then I
tried unsigned short, and it worked for gcc on Linux. I thought it
would be better since unsigned short would only consume 2 bytes, but
int would be 4 bytes(not good thing to do though..)

Prior to C99, C didn't have a boolean type. A lot of code defined its
own type, often using the name "bool", so when the C99 committee
decided to add a boolean type, they couldn't make "bool" a keyword
without breaking existing code. So they introduced the keyword
"_Bool", but they also created the new <stdbool.h> header which
defines "bool" as an alias for "_Bool". (This doesn't break existing
code, since no existing code would have "#include <stdbool.h>".)

But note that both _Bool and bool are C99-specific, and some compilers
might not support it.

In any case, a bit field declared as

some_type bf:1;

will only occupy 1 bit, whatever some_type is. That's the whole
point.

If I wanted a 1-bit bit field, I'd use unsigned int:

unsigned int bf:1;

(A plain int bit field can be either signed or unsigned; that's an
annoyingly odd historical glitch in the language.)
I usually try and error when I code, but could you tell me where
should I refer to write a portable code? I cannot see which standard
document I should check because it looks so many standards exist.

The current official standard for the C language consist of the 1999
ISO C standard plus the three Technical Corrigenda. They've been
conveniently merged into a not-quite-but-almost-official document,
<http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>.

Support for the C99 standard is not yet universal. The C90 standard
is still in wide use. I don't know of a good free source for it.

Note that the standard documents are quite dense; they're definitely
not tutorials. A good tutorial, arguably the best, is "The C
Programming Language", 2nd Edition, by Kernighan & Ritchie (K&R2). It
covers C90, not C99, but that's not much of a problem. A good
reference book is "C: A Reference Manual", 5th Edition, by Harbison &
Steele (H&S5). The comp.lang.c FAQ, <http://www.c-faq.com/>, is
another excellent resource; it also includes a section on other
resources, including some books that I've neglected to mention here.

[...]
OK, thanks for telling me that, though I want to see the reference...

Any decent reference should explain how bit fields are defined. The
real point here, though, is the *lack* of any reference specifying how
bit fields are laid out (though you might find documents that describe
how they're handled by a particular compiler).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top