[comp.lang.c] array of bits field

ping@cubmol.bio.columbia.edu (Shiping Zhang) (02/13/90)

Is there a way to define an array of bits field which are tightly packed?

I tried the following but it caused compiling error.

struct {
    int bits[16]:1;
} bits;

What I intended to do is as following:

first define an union:

union {
    int i;
    struct {
        int bits[16]:1;
    } bits;
} bits;

then assign a ingeter to bits.i;

then get the bit pattern of bits.i via using bits.bits.bits

Thanks.

-ping

davidsen@sixhub.UUCP (Wm E. Davidsen Jr) (02/13/90)

  I don't know of a way to do it in standard C, and if it were added as
an extension I would expect the syntax to be
	int bits:1[16];

  I would find this useful, but I have other things I'd rather see in
the standard. Perhaps in gcc, which seems to have everyone's favorite
feature. 
-- 
	bill davidsen - sysop *IX BBS and Public Access UNIX
davidsen@sixhub.uucp		...!uunet!crdgw1!sixhub!davidsen

"Getting old is bad, but it beats the hell out of the alternative" -anon

henry@utzoo.uucp (Henry Spencer) (02/13/90)

In article <1990Feb12.182517.10921@cubmol.bio.columbia.edu> ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:
>Is there a way to define an array of bits field which are tightly packed?

No.  You have to do the bit-fiddling yourself.  The smallest unit of
storage which is a "first class citizen" in C is the byte.
-- 
"The N in NFS stands for Not, |     Henry Spencer at U of Toronto Zoology
or Need, or perhaps Nightmare"| uunet!attcan!utzoo!henry henry@zoo.toronto.edu

ark@alice.UUCP (Andrew Koenig) (02/13/90)

In article <1990Feb12.182517.10921@cubmol.bio.columbia.edu>, ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:

> Is there a way to define an array of bits field which are tightly packed?

No there isn't.  Sorry about that.

Next question.
-- 
				--Andrew Koenig
				  ark@europa.att.com

brnstnd@stealth.acf.nyu.edu (02/14/90)

In article <1990Feb12.182517.10921@cubmol.bio.columbia.edu> ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:
> Is there a way to define an array of bits field which are tightly packed?

I believe the only solution is to write out each bit separately. It
isn't too painful.

> struct {
>     int bits[16]:1;
> } bits;

You can't point to a bit, so you can't have an array of bits.

---Dan

magik@sorinc.UUCP (Darrin A. Hyrup) (02/14/90)

In article <1990Feb12.182517.10921@cubmol.bio.columbia.edu> ping@cubmol.bio.columbia.edu (Shiping Zhang) writes:
>Is there a way to define an array of bits field which are tightly packed?
>
>I tried the following but it caused compiling error.
>
>[... example deleted ...]

No, under standard C there is no way to do this in the way you're suggesting.
(I wish it were possible too, but alas, no.)

You do have two options.

  1. Define the 16 values as an unsigned int, and use bit manipulation to
     access the individual bits.

      i.e., value &   0x0001 (or 1)   represents the value in bit 1 of "value"
            value &=  0x0040 (or 128) sets the value in bit 7 of "value" to 1
            value |= ~0x0080 (or 128) sets the value in bit 8 of "value" to 0

  2. Define an array of characters that is BITS_NEEDED / BITSIZE elements
     long, and write routines like chkbit(), setbit(), clrbit() to access
     the elements in that array.

     i.e., on a system with 8 bit char's and you need 16 bits...

        char bits[2];

        chkbit(bits,3);   returns 1 or 0 depending on the value of bit 3 in
                          the array bits[];
        setbit(bits,4);   sets bit 4 in bits[] to 1
        clrbit(bits,10);  sets bit 10 in bits[] to 0

     This second method more closely resembles what you were originally
     trying to do.

  When I choose the second option, I usually use macro versions of these
  routines, since the function versions added unwanted overhead. I'll
  include the versions I use below for your convenience:

  These macros assume an 8 bit char, and do no bounds checking.

    #define chkbit(array,n) (array[n / 8] &   (1 << (n % 8)))
    #define setbit(array,n) (array[n / 8] |=  (1 << (n % 8)))
    #define clrbit(array,n) (array[n / 8] &= ~(1 << (n % 8)))

  As you can see, this is just an easier way to do bit manipulations like
  in example 1. If you have something other than an 8 bit char, or want to
  use int's or long's instead of character arrays, change the value "8" in
  the macros to the bitsize of the storage type you are using.

  The main problem with the second example is that you cannot manipulate
  groups of bits at the same time with it, but if you aren't going to need
  it, then the second option is probably easiest.

>Thanks.

You're welcome.  I hope this helps in whatever you're trying to do.

>-ping

Best wishes,

      Darrin Hyrup
--
Darrin A. Hyrup              // AMIGA Enthusiast         rencon!esfenn!dah
magik@sorinc.PacBell.COM   \X/ & Software Developer   pacbell!sorinc!magik
==========================================================================
"Speak little and well, if you wish to be considered as possessing merit."

gary@hpavla.AVO.HP.COM (Gary Jackoway) (02/16/90)

>   1. Define the 16 values as an unsigned int, and use bit manipulation to
>      access the individual bits.
> 
>       i.e., value &   0x0001 (or 1)   represents the value in bit 1 of "value"
>             value &=  0x0040 (or 128) sets the value in bit 7 of "value" to 1
>             value |= ~0x0080 (or 128) sets the value in bit 8 of "value" to 0
I think the &= should be |=, and vice versa.
You can define macros:
    #define TESTBIT(value,bit) (value & (1<<bit))
    #define SETBIT(value,bit) { value &= (1<<bit); }
    #define RESETBIT(value,bit) { value |= ~(1<<bit); }
or something like this.
If the "bit" is a constant, most compilers will pre-compute 1<<bit.
There is a danger with TESTBIT.  You can't compare TESTBIT results.
A safer test bit would be
    #define TESTBIT(value,bit) (value>>bit & 1)
which always gives a 0 or 1 result.
Equivalent would be
    #define TESTBIT(value,bit) !!(value & (1<<bit))

Gary Jackoway

karl@haddock.ima.isc.com (Karl Heuer) (02/16/90)

In article <486@sixhub.UUCP> davidsen@sixhub.UUCP (bill davidsen) writes:
>I don't know of a way to do it in standard C, and if it were added as
>an extension I would expect the syntax to be
>	int bits:1[16];

I would expect "int bits[16]:1", since the declaration is saying that
"bits[i]" has type "int :1".  (Cf. "int (*p[N])()", etc.)

>Perhaps in gcc, which seems to have everyone's favorite feature.

The problem is that, in C, an array name in an rvalue context decays into a
pointer, and due to the rule that sizeof(char) is 1, you can't have pointers
to objects smaller than char.  This doesn't mean the extension couldn't be
implemented, just that it would take some forethought to decide which rules
should be broken in the process.

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