Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: net.lang.c Subject: problems with the C parser Message-ID: <377@dg_rtp.UUCP> Date: Sat, 31-May-86 17:33:01 EDT Article-I.D.: dg_rtp.377 Posted: Sat May 31 17:33:01 1986 Date-Received: Sun, 1-Jun-86 08:40:49 EDT References: <5072@topaz.RUTGERS.EDU> Lines: 70 Summary: gotta use macros to get around this one > brisco@topaz.UUCP > typedef union { > int intfield; /* change the record name - keyword */ > struct bool{unsigned x[32]:1}; > > The C parser barfed all over this. I tried every combination > of unsigned x:1[32], ..... that I could think of. Out of frustration > I looked up the syntax of the declarations in K&R and found that the > initial guess had been correct! > I wanted an integer that I could index into by bit, so I could > avoid using masks (which weren't going to be easily used due to the > methodology of the original program). > Am I going crazy or is our C parser brain-damaged? Can anyone > else compile the above structure declaration? Well. Correcting things to avoid some minor errors, we find typedef union { int intfield; struct {unsigned x[32]:1;} bool; } newtype; which our compiler seems to think means that you want to fit an array of 32 unsigneds into a single bit. It does not approve. Naturally, trying variations of parenthesis around the "x" and the "[32]" doesn't help much, since the :1 is only syntactically legal at the top level of a structure. Which leads to the point. The ":n" bitfield notation is only applicable to integer types, and only when they occur in a structure. It cannot be applied to array members, since array/pointer equivalence insists that each member of an array has an address, and bitfields may not have an address. Similar in notion to trying to declare an array of register variables.... just doesn't work (though most compilers might just overlook that one). Ok, now that we know you can't do what you said you wanted in C, just what *can* be done? Well, you want an array-like construct, so that you can select the bits based on an integer known at run-time. Mask-and-shift can do what you want. Consider the following macros: #define pm(m,p) ((m)<<(p)) /* position mask */ #define mm(w) ((1<<(w))-1) /* make a mask */ #define slice(v,w,p) (((v)&pm(mm(w),(p)))>>(p)) One can now use the "slice" macro to grab an arbitrarily positioned and sized bit field out of an integer typed variable. Bits are counted from the least significant to the most significant, and these macros assume that you've got two's complement arithmetic. They may also not work in full generality on machines that use arithmetic shifts rather than logical shifts. Note that the "position" argument is expanded twice, and thus should be side-effect-free. If you are only interested in single bits, rather than arbitrarily sized bit fields, you can use this macro: #define bit(v,p) (((v)&(1<<(p)))>>(p)) which our compiler seems to choke down effectively. I've left the assign_to_slice and assign_to_bit macros as exersizes for the interested readers. Have fun. -- "Are we having fun yet?" --- from "The Four Seasons" -- Wayne Throop !mcnc!rti-sel!dg_rtp!throopw