[comp.lang.c] bit fields

jpn@teddy.UUCP (John P. Nelson) (12/01/86)

>Ok, folks, here is the burining question of the hour:  how are bit fields in
>C dealt with?  As I read K&R arrays of bit fields are allowed, HOWEVER, in
>the Microsoft C compiler Version 4.0, they explicitly state that they are not
>allowed.

If K&R is Kernighan and Ritchie, I suggest you reread it.  Arrays of bitfields
are EXPLICITLY disallowed  (See the last paragraph in section 6.7) - but in
any case, an array of bitfields is impossible, not just difficult - Remember
that a reference to an array (not just an element of it) evaluates to an
ADDRESS - However, taking the address of a bit field is also explicitly
disallowed.  Here is part of the relavent paragraph from K&R

     Other restritrictions (of bit fields) to bear in mind:  ...   They are
     not arrays; they do not have addresses, so the & operator cannot be
     applied to them.

and again, in appendix A where structures are formally defined (section 8.5):

     ... In all implementations, there are no arrays of fields, and the
     address-of operator '&' may not be applied to them, so that there are no
     pointers to fields.

throopw@dg_rtp.UUCP (Wayne Throop) (12/01/86)

(Note that this discussion in more properly a language discussion, not
 an OS discussion.  I've therefore cross-posted, and set the followup to
 comp.lang.c.)

> wmam@sphinx.UChicago.UUCP (tony mason)
> [...] how are bit fields in C dealt with?  As I read K&R arrays of bit
> fields are allowed [...].  Has X3J11 come up with anything regarding
> this? [...]

Since K&R define array subscripting in terms of pointer arithmetic, and
since taking the address of a bitfield is not allowed by K&R, how can
you possibly conclude that bitfield arrays are allowed?  Breifly,
paraphrasing a lof of what I find in X3J11, bitfield definitions are
legal only on struct members of integral type.  Harbison and Steele warn
that some compilers only allow bitfield modifiers on *unsigned* integral
typed struct members.  K&R say similar things.  So again... what passage
in K&R led you to think that arrays of bitfields were sensible in C?

--
Sometimes I think the only universal in the computing field is the
fetch-execute cycle.
                                --- Alan J. Perlis
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

mark.longo@canremote.uucp (MARK LONGO) (11/10/89)

  I am having a small problem with the RESULT values I get when I call
my FOSSIL.

   I called the request status [AH=03h] to check out what was happening
in the com port, I received 6030h back which is correct:

  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

 This matches up to:

  from left to right:

  Position 5: indicates `clear to send'
  Position 6: indicates `data set ready'

 Etc , etc ..

 Now ALL I need to do is somehow convert this 6030h number into BITS
because EVERY position is important to me.  Does anyone know of a quick
and painless way to do this?

   I was playing with BIT FIELDS, but this did not seem to work.

 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?

  Is there an easier way?

                                     Mark Longo

---
 * Via ProDoor 3.1aR  Bit Systems ~ 330 megs ~ HST ~ Doors ~ (519)767-1755
 * RNet 1.02: CanConf ~ Bit Systems ~ Guelph ~ 519-767-1755 HST

chris@mimsy.umd.edu (Chris Torek) (11/12/89)

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 {
			<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@cs.umd.edu	Path:	uunet!mimsy!chris

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (11/15/89)

In article <20690@mimsy.umd.edu>, chris@mimsy.umd.edu (Chris Torek) writes:

  [  A lot of useful code to break up arbitrary data into bits  ]

  I usually compromise and just force the store by bytes, LSB first. The
technique is virtually the same, except that for portability I assume
that the byte size is 8 (can't be smaller, and makes the access easier).

Then:
        typedef char bitz[sizeof unsigned long];

        bsave(val, dest)
        register unsigned long val;
        bitz dest;
        {
                register int n = 0;

                while (n < sizeof(unsigned long)) {
                        dest[n++] = val & 0xff;
                        val >>= 8;
                }
        }

        /* set a bit */
        void
        setbit(val, dest, bitnum)
        unsigned val, bitnum;
        bitz dest;
        {
                register int offset = val >> 3, shift = val & 7;
                register int temp = dest[offset];

                temp = (temp & ~(1 << shift) | ((val & 1) << shift);
                dest[offset] = temp;
        }

        /* get a bit, 0 or 1 */
        int
        getbit(dest, nitnum)
        bitz dest;
        unsigned bitnum;
        {
                return (dest[val >> 3] & (1 << (val & 7))) != 0;
        }

  Now this method will make testing or setting the bits considerable
slower, but save some space for the storage of the data. Hopefully this
information complements the original posting to provide a starting point
for doing bit manipulation.

  Warning!!! I typed this in rather than pull it from a working program.
It is modulo any typos.
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon

saify@cbnewsl.ATT.COM (saify.lanewala) (11/22/89)

In article <1621@crdos1.crd.ge.COM>, davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes:
> In article <20690@mimsy.umd.edu>, chris@mimsy.umd.edu (Chris Torek) writes:
> 
>   [  A lot of useful code to break up arbitrary data into bits  ]
> 
>>  [ more usefule code here .. ]
>>
>> -- 
>> bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
>>


An early 1989 issue of Dr. Dobbs Journal had a comprehensive article
on bitstring manipulation using C.  I'm sorry I can't remember exactly
which issue had the article, but it's mentioned on the cover.


Good luck.


Saify Lanewala
...!attunix!stl

Daniel_Roedding@fiction.uucp (06/08/90)

Several times I used bit fields to save memory, but I got some trouble when
passing them as parameters to functions.

Take the following example:

typedef struct { ... } the_bitfield;

void somefunct(the_bitfield *argh) {
  /* some stupid code going here */
}

Most compilers do not eat this, since ANSI doesn't allow pointers to
bitfield structures.

I didn't find any way to submit a bitfield-parameter to a function. It
is obvious that pointers to bitfield components aren't allowed, but why
is there no way to get a pointer to the whole structure. ANSI defines a
bitfield to be of the size of an int, so one should get a pointer to it...

I don't want to transfer the parameter by value, because my compiler seems
to create quite stupid code when passing a structured type by value. Further-
more, the function may alter the passed bitfield.

Any solutions?

Daniel

Daniel Roedding         uucp: ..!osu-cis!watzman!tjack!fiction!daniel
Geiststrasse 32               daniel%fiction@watzman.as.sub.org
D-4400 Muenster
++49 251 525306         /* Germans don't need a disclaimer... :-) */

karl@haddock.ima.isc.com (Karl Heuer) (06/13/90)

In article <330617@fiction> Daniel_Roedding@fiction.uucp writes:
>typedef struct { ... } the_bitfield;
>void somefunct(the_bitfield *argh) { ... }
>
>Most compilers do not eat this, since ANSI doesn't allow pointers to
>bitfield structures.

Nonsense.  This is allowed by both Classic C and ANSI C, and it works fine on
the three compilers I tested.  Would you care to post a more complete example?

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

beers@acsu.Buffalo.EDU (Andrew Beers) (06/13/90)

> ...since ANSI doesn't allow pointers to bitfield structures.

No, ANSI doesn't allow pointers to bit fields within structures.

Andrew Beers
------------

beers@autarch.acsu.buffalo.edu
SUNY at Buffalo
Buffalo, NY