problems with the C parser

Wayne Throop throopw at dg_rtp.UUCP
Sun Jun 1 07:33:01 AEST 1986


> brisco at 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      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw



More information about the Comp.lang.c mailing list