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