brisco@topaz.RUTGERS.EDU (T.p.) (05/30/86)
I've been trying to translate a program written in Vax
Pascal to C on our Suns.
My problem arose when I was trying to translate a pascal
variant record structure into a C union structure. The structure type
(in pascal) looked as follows: (keep in mind - both were for 32 bit machines)
newtype = record case selector of
0:(int: unsigned);
1:(bool: packed array [0..31] of boolean);
end
Which I had translated into C as:
typedef union {
int intfield; /* change the record name - keyword */
struct bool{unsigned x[32]:1};
} newtype;
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?
"Wah!"
"No, no. It's 'Wah!'"
"Wah!"
"That's better!"
tp.
chris@umcp-cs.UUCP (Chris Torek) (05/30/86)
In article <5072@topaz.RUTGERS.EDU>, brisco@topaz.RUTGERS.EDU (T.p.), wanting to translate a Pascal packed array [0..31] of boolean writes: > ... I [tried]: > > typedef union { > int intfield; /* change the record name - keyword */ > struct bool{unsigned x[32]:1}; > } newtype; > > 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! Hrum. Where in K&R did you find something that implies the above is in any way correct? Try instead chapter 6, page 138: Other restrictions to bear in mind: fields are unsigned; they may be stored only in int's (or, equivalently, unsigned's); THEY ARE NOT ARRAYS; [emphasis mine] they do not have addresses, so the & operator cannot be applied to them. Arrays must be addressible; bit fields are not addressible; and therefore there are no arrays of bit fields, nor are there bit fields of arrays. As for solving the original problem---obtaining the equivalent of `packed array [0..31] of boolean'---you will probably have to make do with macros, e.g.: #define BIT(name, index) ((name) & (1 << (index))) #define BIS(name, index) ((name) |= 1 << (index)) #define BIC(name, index) ((name) &= ~(1 << (index))) You can, at this point, dispense with the union: typedef long newtype; is probably the best way to go: it is even portable to 16-bitters. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
ark@alice.UucP (Andrew Koenig) (05/30/86)
> 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). C does not offer any kind of bit indexing.
garys@bunker.UUCP (Gary M. Samuelson) (05/30/86)
In article <5072@topaz.RUTGERS.EDU> brisco@topaz.UUCP writes: > typedef union { > int intfield; /* change the record name - keyword */ > struct bool{unsigned x[32]:1}; > } newtype; > Can anyone else compile the above structure declaration? No. You didn't read far enough: "In all implementations, there are no arrays of fields" K&R, p. 197 I tried typedef union { int intfield; struct bool {int x:1; }bit[32]; } newtype; But each bit takes up an entire unsigned, so the size of the above is 32 * sizeof (unsigned). I think you will have to choose from masks, or making each bit a separate field: typedef union { int intfield; struct bool { unsigned x0:1, x1:1, x2:1, x3:1, x4:1, x5:1, x6:1, x7:1, x8:1, x9:1, x10:1, x11:1, x12:1, x13:1, x14:1, x15:1, x16:1, x17:1, x18:1, x19:1, x20:1, x21:1, x22:1, x23:1, x24:1, x25:1, x26:1, x27:1, x28:1, x29:1, x30:1, x31:1; } } newtype; Gary Samuelson
guy@sun.uucp (Guy Harris) (05/30/86)
> typedef union { > int intfield; /* change the record name - keyword */ > struct bool{unsigned x[32]:1}; > } newtype; > > > The C parser barfed all over this. Well, actually, the parser had no trouble with it whatsoever. Some routines that do semantic checking on declarations complained about it. There are plenty of constructs in C which are syntactically valid but not legal C. > I wanted an integer that I could index into by bit... You can't. Read K&R again, only look at more than just the syntax specifications. At the top of page 197: ...In all implementations, there are no arrays of fields... Like it or not, that's the case. It may not be easy to convert your program to use masks, but if you want to convert it to C you have no choice. There *is* a Pascal on Suns, although I don't know if your program uses features specific to VAX(/VMS, I presume) Pascal, which the Berkeley Pascal which Sun offers probably doesn't have. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa
greg@utcsri.UUCP (Gregory Smith) (05/31/86)
In article <5072@topaz.RUTGERS.EDU> brisco@topaz.RUTGERS.EDU (T.p.) writes: > Which I had translated into C as: > > typedef union { > int intfield; /* change the record name - keyword */ > struct bool{unsigned x[32]:1}; > } newtype; > > > The C parser barfed all over this. I tried every combination 'illegal field type', which is what I get, is not an example of parser-vomit by any stretch of the imagination. You did forget the ';' after the 1 in the above, though - which might cause the first '}' to be lost - instant upchuck. And you didn't name the second member of the union - that's not a syntax error, though. >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! > Am I going crazy or is our C parser brain-damaged? Can anyone >else compile the above structure declaration? Well, K&R says that the kinds of things that can put in a bitfield is implementation-defined - thus `declarator : constant_expression'. I think it would be rare, though, to find anything but unsigned ints and ints to be implemented. If an array was allowed, it would be declared as `unsigned x[32]:32', since the width applies to the whole declarator. As it stands, I think you are out of luck. Write 'unsigned bits32' and then use shifts and masks to get at them: #define boolread( rval, bitnum ) ( ((rval)>>(bitnum)) &1) #define boolset( lval,bitnum ) ( (lval) |= 1<<(bitnum)) #define boolclr( lval,bitnum ) ( (lval) &= ~(1<<(bitnum)) #define boolasg( lval,bitnum, new )( new? boolset( lval,bitnum):boolclr(lval\ ,bitnum) -- "We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
throopw@dg_rtp.UUCP (Wayne Throop) (06/01/86)
> 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 <the-known-world>!mcnc!rti-sel!dg_rtp!throopw