[comp.lang.c] bitfields considered harmful?

ckl@uwbln.UUCP (Christoph Kuenkel) (04/27/89)

We have some software using C bitfields like in

	struct ... {
		unsigned	active : 1,
				waiting : 1;
		...
	};

During various ports of that to different SysV machines (should i have posted
that to comp.unix.wizards?) we ran into problems because of compiler bugs.
One time, assembler code was produced that tried to shift a word 0 bits to the
right (68020), another time bitfields read nonzero all the time (iapx386), as
in
	if (x.active) { /* always done */ } else { /* dead code */ }

Now, are bitfields generally considered harmfull?  Are there other good
reasons to avoid them? what does ANSI C say about it?

I like them cause they save space and are much more readable than 
oriing/anding with # defines and i dont have to bother with questions like
how many flags fit into one int.

thanx, christoph
-- 
# include <std/disclaimer.h>
Christoph Kuenkel/UniWare GmbH       Kantstr. 152, 1000 Berlin 12, West Germany
ck@tub.BITNET                ckl@uwbln             {unido,tmpmbx,tub}!uwbln!ckl

gwyn@smoke.BRL.MIL (Doug Gwyn) (04/29/89)

In article <1473@uwbull.uwbln.UUCP> ckl@uwbln.UUCP (Christoph Kuenkel) writes:
>During various ports of that to different SysV machines (should i have posted
>that to comp.unix.wizards?) we ran into problems because of compiler bugs.
>One time, assembler code was produced that tried to shift a word 0 bits to
>the right (68020), another time bitfields read nonzero all the time ...

Yes, I find that people are frequently surprised when I point out that
some machines' shift instructions malfunction if you try to use them to
shift by 0 bit positions.  The proposed C standard allows undefined
behavior for << and >> by negative of too-large amounts, but it requires
shifting by 0 to work.  This means that some implementations are going
to have to generate code to test for a 0 shift count and take different
actions in such a case, unless the compiler is able to determine that it
cannot occur.

>Now, are bitfields generally considered harmfull?  Are there other good
>reasons to avoid them?

The main reason to avoid them is because so many compilers get them wrong.

>what does ANSI C say about it?

Bit-field support is required of a conforming implementation.  Their
properties are left fairly implementation-defined, but not so much so
that the bugs you mentioned are permitted!

>I like them cause they save space and are much more readable than 
>oriing/anding with # defines and i dont have to bother with questions like
>how many flags fit into one int.

Those are good reasons to prefer bit fields.

Sometimes one sees bit fields being used to match externally-imposed
storage layout formats.  This is NOT a good use of bit fields, because
they are not tightly enough constrained to guarantee such detailed
matching.  The compiler could even change its allocation of bit fields
between releases, although it might cause customer complaints if it did.

ftw@masscomp.UUCP (Farrell Woods) (04/29/89)

In article <1473@uwbull.uwbln.UUCP> ckl@uwbln.UUCP (Christoph Kuenkel) writes:
>Now, are bitfields generally considered harmfull?

If they're harmful, then why would we keep them around or use them?

It's tempting to use them for things like mapping hardware device registers
to the bit level, in some kind of device driver.  This is non-portable if I'm
not mistaken, but not explicitly harmful.

>Are there other good reasons to avoid them?

If they're not implemented correctly in your compiler...

>what does ANSI C say about it?

The pANS will tell you what behavior to expect from bitfields, and it will
tell you about some gray areas (implementation-defined) in their definition
and use.


-- 
Farrell T. Woods				Voice:  (508) 392-2471
Concurrent Computer Corporation			Domain: ftw@masscomp.com
1 Technology Way				uucp:   {backbones}!masscomp!ftw
Westford, MA 01886				OS/2:   Half an operating system

bill@twwells.uucp (T. William Wells) (04/30/89)

In article <1473@uwbull.uwbln.UUCP> ckl@uwbln.UUCP (Christoph Kuenkel) writes:
: We have some software using C bitfields like in
:
:       struct ... {
:               unsigned        active : 1,
:                               waiting : 1;
:               ...
:       };
:
: During various ports of that to different SysV machines (should i have posted
: that to comp.unix.wizards?) we ran into problems because of compiler bugs.
: One time, assembler code was produced that tried to shift a word 0 bits to the
: right (68020), another time bitfields read nonzero all the time (iapx386),

Long ago, we at Proximity decided that bit field implementations were
flakey enough that we weren't going to use them.

I see that time hasn't changed this.

Sigh. Bit fields are such a nice idea.

---
Bill                            { uunet | novavax } !twwells!bill

sme@computing-maths.cardiff.ac.uk (Simon Elliott) (05/02/89)

In article <1473@uwbull.uwbln.UUCP>, ckl@uwbln.UUCP (Christoph Kuenkel) writes:
> We have some software using C bitfields like in
> 
> [deleted] 
> 
> I like them cause they save space and are much more readable than 
> oriing/anding with # defines and i dont have to bother with questions like
> how many flags fit into one int.

Well, you may be right about readability, but I don't think you'll find that
you've saved much space in your program.  Oh, you might save it in the
source, but the same shifting and masking is going on under the hood.

Now to the real question - how much space have you saved by packing the data?
probably not a lot, unless you are using tens of booleans.  How much space have
you wasted by generating code to shift and mask?  Depends how often you look
at the flag, right?  Whether or not you save space is a trade-off, like so
many of these religiously-held ideas.  There is no universally-right answer.


-- 
--------------------------------------------------------------------------
Simon Elliott            Internet: sme%v1.cm.cf.ac.uk@nsfnet-relay.ac.uk
UWCC Computer Centre     JANET:    sme@uk.ac.cf.cm.v1
40/41 Park Place         UUCP:     {backbones}!mcvax!ukc!reading!cf-cm!sme
Cardiff, Wales           PHONE:    +44 222 874300

kemnitz@mitisft.Convergent.COM (Gregory Kemnitz) (05/03/89)

In article <885@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes:
> In article <1473@uwbull.uwbln.UUCP> ckl@uwbln.UUCP (Christoph Kuenkel) writes:
> : We have some software using C bitfields like in
> :
> :       struct ... {
> :               unsigned        active : 1,
> :                               waiting : 1;
> :               ...
> :       };
> :

I BELIEVE (I may be wrong) that if a bitfield field (need a better word)
is NEVER used for ANYTHING ELSE (like masks, etc), then code that uses
bitfields is portable (at least between 680X0's and 386's).  However, when
you use a bitfield field with masks and attempt to set the bitfield field
and hope the constitutient bitfields are set right, then you are making
(nonportable) assumptions about the bit ordering in your machine.   Therefore
NEVER use bitfield fields for anything else but bitfields.

				Greg Kemnitz

boyne@hplvli.HP.COM (Art Boyne) (05/04/89)

>sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes:
>In article <1473@uwbull.uwbln.UUCP>, ckl@uwbln.UUCP (Christoph Kuenkel) writes:
>> I like [bitfields] cause they save space and are much more readable than 
>> oriing/anding with # defines and i dont have to bother with questions like
>> how many flags fit into one int.
>
>Well, you may be right about readability, but I don't think you'll find that
>you've saved much space in your program.  Oh, you might save it in the
>source, but the same shifting and masking is going on under the hood.

Whoa!  Whether or not the shifting and masking takes place depends on the
processor you are running on.  With the 68000, single bit bitfields can
be handled with the BCLR, BSET, BCHG, and BTST instructions.  The 68020
has a set of multi-bit bitfield instructions for insertion, extraction,
and testing.

PS. I know that, internally, the processor is still doing shift/mask, but
it isn't taking up my code space!

Art Boyne, boyne@hplvla.hp.com

jimp@asterix.UUCP (Jim Patterson) (05/04/89)

In article <705@cf-cm.UUCP> sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes:
>In article <1473@uwbull.uwbln.UUCP>, ckl@uwbln.UUCP (Christoph Kuenkel) writes:
>> We have some software using C bitfields like in
>> I like them cause they save space ...
>Well, you may be right about readability, but I don't think you'll find that
>you've saved much space in your program.  Oh, you might save it in the
>source, but the same shifting and masking is going on under the hood.

This may be so if the computer doesn't have bitfield operations, but
many (e.g. VAX, MC68020, 80286) have instructions that implement
bitfields directly. Even single-bit test and set instructions are
worthwhile as bit-flags are quite common. These instructions can
result in considerably shorter code sequences as they deal with small
numbers (usually in the range 0 to 31, i.e. 5 bits) instead of large
32-bit masks.

Most compilers aren't smart enough to "optimize" a series of ands/ors
and shifts into bitfield access.
-- 
Jim Patterson                              Cognos Incorporated
UUCP:decvax!utzoo!dciem!nrcaer!cognos!jimp P.O. BOX 9707    
PHONE:(613)738-1440                        3755 Riverside Drive
                                           Ottawa, Ont  K1G 3Z4

chris@mimsy.UUCP (Chris Torek) (05/06/89)

In article <6047@asterix.UUCP> jimp@asterix.UUCP (Jim Patterson) writes:
>many [machines] have instructions that implement bitfields directly.

And on many of these, the special instructions are *slower* than the
equivalent sequence of and/or/shifts....

That is why we leave the instruction choice to the compiler, and merely
include bitfields as a convenience to the programmer.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

wayne@dsndata.uucp (Wayne Schlitt) (05/07/89)

In article <705@cf-cm.UUCP> sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes:
>In article <1473@uwbull.uwbln.UUCP>, ckl@uwbln.UUCP (Christoph Kuenkel) writes:
>> We have some software using C bitfields like in
>> 
>> [deleted] 
>> 
>> I like them cause they save space and are much more readable than 
>> oriing/anding with # defines and i dont have to bother with questions like
>> how many flags fit into one int.

>Well, you may be right about readability, but I don't think you'll find that
>you've saved much space in your program.  Oh, you might save it in the
>source, but the same shifting and masking is going on under the hood.

>Now to the real question - how much space have you saved by packing the data?
>probably not a lot, unless you are using tens of booleans.  How much space have
>you wasted by generating code to shift and mask?  Depends how often you look
>at the flag, right?  Whether or not you save space is a trade-off, like so
>many of these religiously-held ideas.  There is no universally-right answer.

you are correct.  using bit fields and floats (instead of doubles)
will often _cost_ you more space than you save.  it will usually also
slow down your program a great deal.

as a rule of thumb, i figure that every reference to an int variable
will cost you about 2-6 bytes of code, but references to bit fields
will cost you 4-20 bytes code.  references to floats are often as bad,
if not worse since the often require a subroutine call.  the only way
you can end up saving space is if you use the bit fields or floats in
a very large array.



-wayne

mat@mole-end.UUCP (Mark A Terribile) (05/07/89)

> > We have some software using C bitfields ... I like them cause they save
> > space and are much more readable than oriing/anding with # defines and I
> > dont have to bother with questions like  how many flags fit into one int.

Also, when you have an existing data layout which is NOT packed, and you have
to pack it, bitfields can save your pretty little butt--assuming that you've
used structs ``like you're supposed to.''

> Well, you may be right about readability, but I don't think ... you've saved
> much space in your program. ... the same shifting and masking is going on ...

> Now to the real question - how much space have you saved by packing the data?
> probably not a lot, unless you are using tens of booleans. ...

If you have several thousand instances of a struct, and if you can store ten
bytes each instead of twenty-eight, you've saved a lot.  Maybe not a lot on a
PC with two megabytes, but a lot for a TSR program or an awful lot in an
embedded system whose price will depend strongly on how much RAM you have to
build into it.

> How much space have you wasted by generating code to shift and mask?
> Depends how often you look at the flag, right?  Whether or not you save
> space is a trade-off, like so many of these religiously-held ideas.  There
> is no universally-right answer.

Remember that memory is not memory.  In an embedded system, there may be
ten or one hundred bytes of ROM available for every byte of RAM.

I worked on such a system; it's one that you've probably seen advertised.
We saved our tender parts by going to bitfields, even though many of our
programmers were not really familiar with them.  We needed to move a unit-
cost/functionality curve by packing the bits, and they were used in so many
places (throughout some three hundred thousand lines of code) that going over
the code just once to make the change would have delayed us past our market
window.  It was, simply put, unthinkable.  (And I did once make a change
that required changing hundreds of uses of one datum through about two
thirds of the system.  Our release librarian at first didn't believe that
one change could touch over two hundred source files.  The alternative to
that one change was a similar number of instances of different changes, so
the developers OK'd it.)

Dennis Ritchie once called bitfields ``a botch and a blemish.''  Are they?
Compared to the rest of C and C++, you bet.  Have they saved their users
millions of dollars?  I can testify that they have.

What the trade-offs are depends on your circumstances.  Aesthetics,
science, and economics are all vital concerns of the Useful Arts of
Engineering.  None of them by itself IS Engineering.
-- 

(This man's opinions are his own.)
From mole-end				Mark Terribile

marcus@illusion.UUCP (Marcus Hall) (05/09/89)

In article <340011@hplvli.HP.COM> boyne@hplvli.HP.COM (Art Boyne) writes:
]>sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes:
]>In article <1473@uwbull.uwbln.UUCP>, ckl@uwbln.UUCP (Christoph Kuenkel) writes:
]>> I like [bitfields] cause they save space and are much more readable than 
]>> oriing/anding with # defines and i dont have to bother with questions like
]>> how many flags fit into one int.

]>Well, you may be right about readability, but I don't think you'll find that
]>you've saved much space in your program.  Oh, you might save it in the
]>source, but the same shifting and masking is going on under the hood.

]Whoa!  Whether or not the shifting and masking takes place depends on the
]processor you are running on.  With the 68000, single bit bitfields can
]be handled with the BCLR, BSET, BCHG, and BTST instructions.  The 68020
]has a set of multi-bit bitfield instructions for insertion, extraction,
]and testing.
]
]PS. I know that, internally, the processor is still doing shift/mask, but
]it isn't taking up my code space!

All the compilers that I have worked on can easily optimize shifting and
masking operations into bitfield operators.  It isn't really very hard to
catch most all cases, anding or oring with a constant is a good indication
that the optimization should be looked for.

Machines that don't have explicit bit operations often have to do as much
optimization to get decent performance out of bitfields.  Many times the
bitfield operations are broken, or have bad optimization (as has been
pointed out already).

marcus hall