making it easier to use unions

Rick Genter rgenter at BBN-LABS-B.arpa
Fri Jun 27 06:46:07 AEST 1986


     Quite often, one will see a union used in a context similar to the
following:

	struct	device	{
		union	{
			unsigned short	_dr_word1;
			struct	{
				unsigned _dr_bit1  : 1;
				unsigned _dr_bit2  : 1;
				unsigned _dr_value : 3;
				unsigned	   : 2;
				unsigned _dr_ctrl  : 1;
				unsigned _dr_val2  : 8;
			} _dr_w1;
		} _dr_u1;

		unsigned short	dr_data;

		union	{
			< another control word >
		} _dr_u2;
	};

followed by a whole bunch of #defines like:

	#define	dr_word1	_dr_u1._dr_word1
	#define	dr_bit1		_dr_u1._dr_w1._dr_bit1
	#define	dr_value	_dr_u1._dr_w1._dr_value

usually bracketed by a comment saying something about "making it easier to
access the bit fields."  The reason for using the union in the first place
is that you want to write your device driver in an obvious manner - if you
want to assert the 'bit1' bit in the first control register, you want to
say something like:

	dp->dr_bit1 = 1;

(we'll ignore the issue of bit-field ordering and portability for now) - yet
you have to actually write the control register as a word because it is a
write-only register and the only bit manipulation instructions your processor
executes are read-modify-write, causing you to keep a software copy of the
register.

     It would be nice if we could do away with the intermediate labels
on structures/unions used in this manner.  It seems to me that it
should be possible given the constraint that within the enclosing
context for the structure/union declaration in question, field names
must be unique.  In my mind, this is merely an extension of insisting
that field names within a structure/union declaration be unique.

     Using the above example, we could define 'struct device' as:

	struct	device	{
		union	{
			unsigned short	dr_word1;
			struct	{
				unsigned dr_bit1  : 1;
				unsigned dr_bit2  : 1;
				unsigned dr_value : 3;
				unsigned	   : 2;
				unsigned dr_ctrl  : 1;
				unsigned dr_val2  : 8;
			};	/* <= note there is no label here */
		};		/* <= nor here */

		unsigned short	dr_data;

		union	{
			< another control word >
		};		/* <= nor here */
	};

Then if you had a variable 'dp' declared as (struct device *), you could
just reference dp->dr_bit1 directly, without going through all of that 
#define nonsense and without saying dp->_dr_u1._dr_w1._dr_bit1.  Only objects
of type 'struct device' would be able to reference the fields 'dr_bit1', etc.,
without generating a warning ("warning: illegal member use: dr_bit1").

     Now, someone tell me why this would be bad to add to X3J11.  My
apologies if it has already been added; my copy is the April 30, 1985 draft
and I haven't incorporated the 9 articles worth of changes which were
posted a couple of months ago into it yet (1/2 :-).

(By the way, accessing device registers is not the only application for
using structures/unions as shown.  Other applications include protocol
implementations, and interpreting binary files with complex record formats.)
--------
Rick Genter 				BBN Laboratories Inc.
(617) 497-3848				10 Moulton St.  6/512
rgenter at labs-b.bbn.COM  (Internet new)	Cambridge, MA   02238
rgenter at bbn-labs-b.ARPA (Internet old)	linus!rgenter%BBN-LABS-B.ARPA (UUCP)



More information about the Comp.lang.c mailing list