print out ascii characters

Y

Yoshi

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.

very interesting story, then actually we would better not use _Bool
after all.

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.

Let me ask this point. since below code shows different size according
to each types(_Bool, unsigned short, unsigned int). so does it really
consume only 1 bit? I think I'm missing something..

It looks like each bit field consumes only 1 bit, but other bits are
not used in case of unsigned short and unsigned int.

#include <stdio.h>

typedef struct _mychar_b{
_Bool seven: 1;
_Bool six: 1;
_Bool five: 1;
_Bool four: 1;
_Bool three: 1;
_Bool two: 1;
_Bool one: 1;
_Bool zero: 1;
}mychar_b;

typedef struct _mychar_short{
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;
}mychar_short;


typedef struct _mychar_int{
unsigned int seven: 1;
unsigned int six: 1;
unsigned int five: 1;
unsigned int four: 1;
unsigned int three: 1;
unsigned int two: 1;
unsigned int one: 1;
unsigned int zero: 1;
}mychar_int;

int main(void)
{
printf("sizeof mychar_b = %d\n",sizeof(mychar_b));
printf("sizeof mychar_short= %d\n",sizeof(mychar_short));
printf("sizeof mychar_int = %d\n",sizeof(mychar_int));
return 0;
}


Output is...

sizeof mychar_b = 1
sizeof mychar_short= 2
sizeof mychar_int = 4
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.)


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.

Thank you for valuable information, I'm being overwhelmed to find that
pdf file is over 550pages...but I think I should get H&S5 anyway.

[...]
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).
That's awesome, so I should not use bit fields for the case I need to
expect certain layout of bit fields. But how inconvenient!
 
Y

Yoshi

Maybe this is helpful.

void bits(unsigned char b, int n) {
    for (--n; n >= 0; --n)
       putchar((b & 1 << n) ? '1' : '0');
    putchar(' ');

}

Thank you, using putchar looks simpler and clearer.
 
K

Keith Thompson

Yoshi said:
very interesting story, then actually we would better not use _Bool
after all.

It depends.

A lot of compilers do support much of C99, and support can be expected
to improve as time passes. If you want to use C99's boolean type,
it's probably best to use "#include <stdbool.h>" and refer to "bool"
rather than "_Bool".

You can even declare something very similar to C99's bool in C90:

typedef enum { false, true } bool;

It's not exactly equivalent in all cases, but it's close enough if
you're reasonably careful. You might try something like this:

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif

(Or you can just use 0, 1, and int, as C programmers have been
doing for years.)

Of course the FAQ discusses this; see section 9.
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.

Let me ask this point. since below code shows different size according
to each types(_Bool, unsigned short, unsigned int). so does it really
consume only 1 bit? I think I'm missing something..

It looks like each bit field consumes only 1 bit, but other bits are
not used in case of unsigned short and unsigned int.
[code snipped]

Output is...

sizeof mychar_b = 1
sizeof mychar_short= 2
sizeof mychar_int = 4

Hmm. Yes, it appears that the type chosen for a bit field, at least
with some compilers, can affect the size of the structure as a whole.
This happens with gcc, and I've seen it before with other compilers (I
meant to mention that). I don't know why they do this. Perhaps the
alignment for the structure is based on the alignment of the
*declared* type of the bit field, even though it really shouldn't have
any effect.

The standard doesn't say anything about this; it's within the rather
wide range of permitted behavior, but I personally find it quite odd.

[...]
That's awesome, so I should not use bit fields for the case I need to
expect certain layout of bit fields. But how inconvenient!

Unless you're willing to depend on the behavior of a particular
compiler (which might change with the next version).
 
N

Nick

Ben Bacarisse said:
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.

If you read right to left, Ben's suggestion comes out as: "byte" is a
constant that points to a character which is unsigned and constant.

If you're going to put "const" in (unsigned char *byte would do by
itself), then you might as well put as many as you can in.
 
B

bartc

Nick said:
If you read right to left, Ben's suggestion comes out as: "byte" is a
constant that points to a character which is unsigned and constant.

If you're going to put "const" in (unsigned char *byte would do by
itself), then you might as well put as many as you can in.

I had certain problems with pete's code (which is why I also posted a
version), but this was the main issue:

const unsigned char *const byte = s2;

How obfuscatory is that? 4 attributes to declare a simple pointer, or is it
5 -- or 6? Or perhaps 3. But why am I even wasting time counting?

At first there appears to be no type, until you spot 'char' in the middle.
Then it
looks like there is no variable defined (as my brain sees 'byte' as a type).
Then it's difficult to reconcile 'byte' with what this actually variable is,
a pointer to a char.

I think all const attributes should be banned, as they seem to contribute
nothing except making code look cluttered (and probably hiding the real
problems).

My version of that declaration would look something like:

char *p = s2;

(Or would do if there wasn't this business about sometimes chars having to
be unsigned. Which means either using unsigned char everywhere, or analysing
the code to see whether it will work with signed... but of course this is
trivial matter..)
 
Y

Yoshi

If you read right to left, Ben's suggestion comes out as: "byte" is a
constant that points to a character which is unsigned and constant.

I'm still confused, then the second 'const' in the following line does
not mean anything?
const unsigned char const *byte;
 
A

Alan Curry

I'm still confused, then the second 'const' in the following line does
not mean anything?
const unsigned char const *byte;

It means exactly what the first one means. Having both of them is redundant.
 
B

Ben Bacarisse

Malcolm McLean said:
There's no nice way of printing put binary in C. However it is easy.

voud printb(FILE *fp, unsigned char ch)
{
int i;
int mask = 1 << (CHAR_BIT -1);

for(i=0;i<CHAR_BIT;i++)
{
fputc(fp, (ch & mask) ? '1' : '0')
mask >>= 1;
/* for pathological platforms where sizeof int == 1 */
if( (mask & (1 << (CHAR_BIT - 1)) )
mask = 1 << (CHAR_BIT -2);

It's too late to try to fix the problem here. The initial setting of
mask is undefined when 2**CHAR_BIT - 1 is not representable so there
is little value in trying to fix the problem of implementation-defined
signed left shifts.

The problem goes away if you make mask an unsigned int.
 
B

Ben Bacarisse

pete said:
The left operand of those shift operations,
should also be unsigned.

unsigned mask = 1u << (CHAR_BIT -1);

Yes. I took it as read that if you changed the type you'd use the
right type to initialise it, especially as the problem I was pointing
out was that 1 << (CHAR_BIT - 1) is undefined (in the specific case
that was being considered).
 

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,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top