Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!haven!mimsy!chris From: chris@mimsy.umd.edu (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Bit Fields Message-ID: <20690@mimsy.umd.edu> Date: 12 Nov 89 04:05:01 GMT References: <89111105491001@masnet.uucp> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 106 In article <89111105491001@masnet.uucp> mark.longo@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 { }; 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@cs.umd.edu Path: uunet!mimsy!chris