[comp.lang.c] "address" of a bitfield

wiml@blake.acs.washington.edu (William Lewis) (07/17/89)

   For the usual reasons, I have to pass the address of a variable to
a function. (The function needs to read, and possibly modify, any of a 
large number of variables of diverse types.)  Unfortunately, many of these
variables are bitfields, and, obviously, bitfields don't strictly *have*
an address. Ideally, there is a macro I could write to get something along
the lines of:
  
   BitFAddr(thing.field, start, offset, width);

  which would assign to 'start' the (char *) pointing to the start of the
bitfield, to 'offset' the number of bits into the char the bitfield starts,
and to 'width' the width of the bitfield in bits. Using this info, I
could read & write the bitfield using '<<' and the bitwise operators.
    Does anyone know of an even semi-portable way to do this? Or, if
there is no portable way, a way that works with Mark Williams C on
a MSDOS machine? 
    Otherwise, I have to assign all my bitfields (many of which are only
1 bit wide) to chars, and transcribe them back again after the function 
call, to get the same effect, but with lots of ugly gunk around it...

    --- phelliax
        "&(foo.fie.fo -> fum.ziz.clf[grot->thup])"

wht@tridom.uucp (Warren Tucker) (07/17/89)

In article <2840@blake.acs.washington.edu>, wiml@blake.acs.washington.edu (William Lewis) writes:
> 
>    BitFAddr(thing.field, start, offset, width);
>   which would assign to 'start' the (char *) pointing to the start of the
> bitfield, to 'offset' the number of bits into the char the bitfield starts,
> and to 'width' the width of the bitfield in bits. Using this info, I
> could read & write the bitfield using '<<' and the bitwise operators.
>
Completely non-portable, but that may be ok for you (the actual 
format of bit fields are are left to the compiler writer's whim).
Try passing the address of the structure to a function that knows which
field to manipulate.
The best way to be portable would be to scrap bitfields alllll tooogether
and use #defines for bit masks.

rec@elf115.uu.net (Roger Critchlow) (07/17/89)

In article <2840@blake.acs.washington.edu>, wiml@blake.acs.washington.edu (William Lewis) writes:
> 
> [reasonable reasons for wanting the address of a bitfield]
>
>     Does anyone know of an even semi-portable way to do this? Or, if
> there is no portable way, a way that works with Mark Williams C on
> a MSDOS machine? 

There isn't currently any way to do this with the Mark Williams compiler,
and there is no way to do this defined by the dpANS.

But, I note that the result of the dpANS offsetof() macro is undefined
when applied to a bitfield member, and if a compiler treated this macro
with special care it might be possible to provide the necessary infor-
mation for those who need it.

One possibility would be for offsetof(type, bit-field-member) to generate
a triple of constants:

  bit_offset_constant, bit_width_constant, byte_offset_constant

which could be plugged into a user defined function call argument list to
a bit field pointer constructor.

Does anyone see any problems with this as an extension to dpANS?

-- rec@elf115.uu.net --

henry@utzoo.uucp (Henry Spencer) (07/18/89)

In article <2840@blake.acs.washington.edu> wiml@blake.UUCP (William Lewis) writes:
>  which would assign to 'start' the (char *) pointing to the start of the
>bitfield, to 'offset' the number of bits into the char the bitfield starts,
>and to 'width' the width of the bitfield in bits...
>    Does anyone know of an even semi-portable way to do this? ...

Can't be done -- the packing of bitfields into words/chars/whatever is
highly machine-specific (even the order, left-to-right or right-to-left,
varies) and the information is not available to the program.
-- 
$10 million equals 18 PM       |     Henry Spencer at U of Toronto Zoology
(Pentagon-Minutes). -Tom Neff  | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

norm@oglvee.UUCP (Norman Joseph) (07/18/89)

From article <2840@blake.acs.washington.edu>, by wiml@blake.acs.washington.edu (William Lewis):
> 
>    For the usual reasons, I have to pass the address of a variable to
> a function. (The function needs to read, and possibly modify, any of a 
> large number of variables of diverse types.)  Unfortunately, many of these
> variables are bitfields, and, obviously, bitfields don't strictly *have*
> an address. Ideally, there is a macro I could write to get something along
> the lines of:
>   
>    BitFAddr(thing.field, start, offset, width);

Bitfields themselves don't have addresses, but the struct of which
they are a part do.  Why not pass a pointer to the whole struct
containing the bitfields?  One drawback of this approach is that the
function now needs to know about the struct.  Would that be so bad
in your case?  If your function needs access to "a large number of
variables of diverse types", it might be worthwhile, if the design
lends itself, to keep these variables together in a struct and pass
a pointer to one of these structs as an argument instead of a long
list of diverse types.

>     Does anyone know of an even semi-portable way to do this? Or, if
> there is no portable way, a way that works with Mark Williams C on
> a MSDOS machine? 

From K&R, 1ed., p.45:

        getbits( x, p, n )    /* get n bits from position p in x */
         unsigned x, p, n;
        {
            return (( x >> ( p + 1 - n )) & ~( ~0 << n ));
        }

As the authors describe it:  "...returns (right adjusted) the n-bit field
of x that begins at position p.  We assume that bit position 0 is at the
right end and that n and p are sensible positive values."

This should be useful as a starting point.

>     Otherwise, I have to assign all my bitfields (many of which are only
> 1 bit wide) to chars, and transcribe them back again after the function 
> call, to get the same effect, but with lots of ugly gunk around it...

Even if you needed to do this, you would want to use unsigned ints, since
chars are widened to ints before being passed as function arguments or
used in expressions.

>     --- phelliax
>         "&(foo.fie.fo -> fum.ziz.clf[grot->thup])"
-- 
Norm Joseph - Oglevee Computer System, Inc.
  UUCP: ...!{pitt,cgh}!amanue!oglvee!norm
    /* you are not expected to understand this */

hascall@atanasoff.cs.iastate.edu (John Hascall) (07/18/89)

In article <utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <@blake.acs.washington.edu> wiml@blake.UUCP (William Lewis) writes:
 
>>  which would assign to 'start' the (char *) pointing to the start of the
>>bitfield, to 'offset' the number of bits into the char the bitfield starts,
>>and to 'width' the width of the bitfield in bits...
>>    Does anyone know of an even semi-portable way to do this? ...
 
>Can't be done -- the packing of bitfields into words/chars/whatever is
>highly machine-specific (even the order, left-to-right or right-to-left,
>varies) and the information is not available to the program.

    But it is available to the compiler!  Which is what I think Mr. Lewis
    was thinking of--that it be handled like the "sizeof" operator.

    It seems like useful information, but perhaps separate operators would
    be more convenient:

	 bit_sizeof(foo)
	 bit_offsetof(foo)
	 bit_baseof(foo)

    John Hascall  /  ISU Comp Center  /  Ames IA

bgbg@cbnewsd.ATT.COM (brian.g.beuning) (07/19/89)

>     Does anyone know of an even semi-portable way to do this?

How about something like this?  If you want to describe the
bitfields of struct x

	struct x {
		int	a: 2;
		int	b: 3;
		int	c: 5;
	} y;

for each field (using 'a' as an example) do,

	1. set all of 'y' to zero (using memset or bzero)
	2. set y.a = ~0 (all 1's, compiler will truncate unless
		your compiler allows bitfield's larger than int)
	3. see which bits of y have changed (from zero) and set
		start, offset, and width appropriately.

For step 3 use an array of int's that overlay 'struct x'
(or equivalently a
	union _x {
		struct x	main;
		int		array[ sizeof(struct x) / sizeof(int) ];
	} _y;
).
search _y.array[] for a non-zero entry (this gives start)
then search this int for the first '1' and the last '1'
(these give offset and width).

The question in my mind is the big- vs. little-endian problem.
Is it possible that there could be two strings of 1's if the
bitfield crosses a char or short boundary?

The above must be done every time your program executes in
an initialization routine.

Brian Beuning

shap@bunker.UUCP (Joseph D. Shapiro) (07/21/89)

In article <2840@blake.acs.washington.edu> wiml@blake.UUCP (William Lewis) writes:
>
>   For the usual reasons, I have to pass the address of a variable to
>a function. (The function needs to read, and possibly modify, any of a 
>large number of variables of diverse types.)  Unfortunately, many of these

this may not apply, but you should probably consider not passing the
address, but the value, and use something like:

	x = function(x);

if function is declared as

	unsigned long function(unsigned long x);

the compiler will do all the type conversions for you, even for bit fields.
-- 
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
Joe Shapiro					"My other car is a turbo...
ISC-Bunker Ramo     				 ...too."
{decvax,yale,philabs,oliveb}!bunker!shap

ray@philmtl.philips.ca (Raymond Dunn) (07/21/89)

In article <611@cbnewsd.ATT.COM> bgbg@cbnewsd.ATT.COM (brian.g.beuning) writes:
>>     Does anyone know of an even semi-portable way to do this?
>
>How about something like this?  If you want to describe the
>bitfields of struct x....
> [complex ad-hoc kludge omitted]

Whether this works or not is irrelevant to the main issue.

If you have to fight a language to this degree to make it do something for
you then you either have chosen the wrong langauge for the task or you have
designed your implementation (structures and/or logic) in a way inappropriate
for that language.

There are some things that C does superbly.  The integration of the concept
of structure member selectors in the langauge is not one of them.  Neither
is the handling of types less than 1 byte in size.
-- 
Ray Dunn.                    | UUCP: ..!uunet!philmtl!ray
Philips Electronics Ltd.     | TEL : (514) 744-8200  Ext: 2347
600 Dr Frederik Philips Blvd | FAX : (514) 744-6455
St Laurent. Quebec.  H4M 2S9 | TLX : 05-824090