Bit Fields
Chris Torek
chris at mimsy.umd.edu
Sun Nov 12 15:05:01 AEST 1989
In article <89111105491001 at masnet.uucp> mark.longo at canremote.uucp
(MARK LONGO) writes:
> What I want to do is translate this HEX value into BINARY so I can
>check what `each bit' means.... For example: 6030h = 0110000000110000
>in base 2 ... Position 5: indicates `clear to send' ...
>
> Now ALL I need to do is somehow convert this 6030h number into BITS
>because EVERY position is important to me.
It is not clear to me what you *really* want to do. Values stored in
a typical modern computer *are* in bits, no matter how they are written
when communicating with a person.
If you want to read and write binary values in C, you have to write your
own formatting and scanning functions, such as:
/*
* Convert a value to nbits bits into a buffer of at least nbits+1
* characters. Return the beginning of the buffer.
*/
char *btostr(char *buf, int nbits, long int value) {
unsigned long int t = value;
if (nbits <= 0)
panic("invalid call to btostr");
buf += nbits; /* bits generated backwards */
*buf = 0;
do {
*--buf = (t & 1) + '0';
t >>= 1; /* unsigned shift */
} while (--nbits > 0);
return (buf);
}
/* strtob is left to the reader */
/* (hint: it can be done with strtol or strtoul) */
You can then write, e.g.,
char bitbuf[13];
printf("1234 = 0b%s\n", btostr(bitbuf, 12, 1234L));
If, instead, you want to test individual bits, you have a number of
different options, including bitfield structures. I do not recommend
bitfield structures, as they tend to (a) tickle compiler bugs, (b)
produce poor (large and/or slow) code once these bugs are worked around,
and (c) be nonportable since two different compilers for the same
machine will produce different bit orders.
>It would be nice if i could do something like:
> struct modem {
> unsigned clear_to_send : 1;
> unsigned data_set_ready: 1;
> .
> .
> unsigned time_out :1;
> } code;
>then put the 6030h into base 2 and throw it into code . Can it be done?
If you are determined to use bitfields despite my dire predictions ( :-) )
above:
union foo {
struct modem {
<bits>
};
short sixteen_bits;
} code;
code.sixteen_bits = 0x6030;
I find the simplest thing is to use `#define's for each bit group:
#define FOO_CTS 0x0001 /* clear to send */
#define FOO_DSR 0x0002 /* data set ready */
...
#define FOO_TO 0x8000 /* timeout */
And:
#define FOO_BITS \
"\020TO\017...\002DSR\001CTS"
and a `printf-like' function that prints a bit-value using the above:
/* s points to FOO_BITS; b = value to print */
any = 0;
while ((i = *s++) != 0) {
if (b & (1 << (i-1))) {
(void) putchar(any ? ',' : '<');
any = 1;
for (; (c = *s) > 32; s++)
(void) putchar(c);
} else
for (; *s > 32; s++)
/* void */;
}
if (!any)
(void) putchar('<');
(void) putchar('>');
(Note that the above assumes ASCII coding or similar, such that
none of the letters to be printed with each bit have codes <= 32.
It also means at most 32 bits can be examined in this way.)
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at cs.umd.edu Path: uunet!mimsy!chris
More information about the Comp.lang.c
mailing list