Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!caip!brl-adm!brl-smoke!smoke!rgenter@BBN-LABS-B.arpa From: rgenter@BBN-LABS-B.arpa (Rick Genter) Newsgroups: net.lang.c Subject: making it easier to use unions Message-ID: <1725@brl-smoke.ARPA> Date: Thu, 26-Jun-86 16:46:07 EDT Article-I.D.: brl-smok.1725 Posted: Thu Jun 26 16:46:07 1986 Date-Received: Mon, 30-Jun-86 05:28:31 EDT Sender: news@brl-smoke.ARPA Lines: 92 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@labs-b.bbn.COM (Internet new) Cambridge, MA 02238 rgenter@bbn-labs-b.ARPA (Internet old) linus!rgenter%BBN-LABS-B.ARPA (UUCP)