Standard C Digest - V2 #8

Orlando Sotomayor-Diaz osd7 at homxa.UUCP
Fri Jan 11 22:17:52 AEST 1985


ANSI Draft of Proposed  C Language Std.

Mail your replies to the author(s) below or to cbosgd!std-c.
Cbosgd is reachable via most of the USENET nodes, including ihnp4,
ucbvax, decvax, hou3c....  Administrivia should be mailed to 
cbosgd!std-c-request.

ARPA -> mail to cbosgd!std-c at BERKELEY.ARPA (+++ NOT TO INFO-C +++)

**************** mod.std.c  Vol. 2 No. 8  1/11/85 *******************

Today's Topics:
	On Decot's union initialization scheme; another method (1)
----------------------------------------------------------------------

Date: Thu, 10 Jan 85 15:45:50 est
From: cbosgd!watmath!kpmartin (Kevin Martin)
Subject: Union initialization; a better method

In the following, 'you' refers to Dave Decot (hpdsa!decot). He writes:
>Here goes a proposal you might have heard before.  Please let me know if
>there are any flaws in it.  So far, nobody has been able to shoot it down.
>
>If the data used to initialize the union is appropriately cast, and that
>data type is a valid member of the union, then there is no ambiguity nor
>problem; the union will hold the value by definition, and the data will
>be appropriately cast.
No one can shoot it down, because it is probably sufficient to solve the
problem. That doesn't make it a good solution.

The problem with this method is that it lacks the ability to make
the code self-documenting. Reading the code sample you give, all I can tell
is that (for cell[1]), you are initializing one of the (char *)'s in the
union to a pointer to "abc". It doesn't tell me *directly* which element
you are initializing.
For similar reasons, it is error-prone, due to C's implicit type conversions
(e.g. if you neglected to declare (or mis-declared) the cv_char element,
or mis-cast the value, call[0] would not receive the initialization
you expected).
In addition it causes an explicit cast to behave differently from an
implicit type conversion to the same type, that is, this would be the
only place in C where
	(type) (expr)
would be different from
	(expr)    /* implicitly cast into (type) */

As I said above, it works, but there are better solutions. Given that a
syntactic change is required (you requires one to allow casting of
aggregates when initializing a union of two structs whose elements are
similarly typed), here is an alternative, which solves the problems I
have voiced:
Allow the initializer to be preceded by "element_name =" to name a specific
element. If no element is named, the first element is initialized. The
initializers are checked for type compatibility, just as they currently are
for non-union initializers.

For reference, here is your example again: (correcting a typo, cv_char_p
should have read cv_char_a in one place)
>	#define UNKNOWN 00
>	#define CHAR	01
>	#define CHAR_P	02
>	#define CHAR_A	03
>	#define SHORT	04
>	#define LONG	05
>	#define FLOAT	06
>	#define DOUBLE	07
>	#define SHORT_A	010
>
>	struct {	/* I know it doesn't have a name */
>	    int	CellType;	/* holds one of the above defines */
>	    union {
>		char	cv_char;
>		char	*cv_char_p;
>		char	cv_char_a[4];
>		short	cv_short;
>		long	cv_long;
>		float	cv_float;
>		double	cv_double;
>		short	cv_short_a[4]
>	    } cv;
>	} cell[10] = {
>	    {CHAR,	'?'},
>	    {CHAR_P,	(char *)"abc"},
>	    {CHAR_A,	(char [])"abc"},
>	    {CHAR_A,	(char []){'a', 'b', 'c'}}, /* doesn't need the cast */
>	    {DOUBLE,	(double)2},
>	    {SHORT_A,	(short[]){0, 1, 2}}	/* last element is 0? */
>	    /* If the rest of the storage is initialized to 0,
>	    ** note that a check would show a type of UNKNOWN.
>	    */
>	};

Here is the initialization of the same struct, using the method I am
proposing:
	struct {	/* I know it doesn't have a name */
	    int	CellType;	/* holds one of the above defines */
	    union {
		char	cv_char;
		char	*cv_char_p;
		char	cv_char_a[4];
		short	cv_short;
		long	cv_long;
		float	cv_float;
		double	cv_double;
		short	cv_short_a[4]
	    } cv;
	} cell[10] = {
	    {CHAR,	cv_char = '?'},
	    {CHAR_P,	cv_char_p = "abc"},
	    {CHAR_A,	cv_char_a = "abc"},
	    {CHAR_A,	cv_char_a = {'a', 'b', 'c'}},
	    {DOUBLE,	cv_double = 2},
	    {SHORT_A,	cv_short_a = {0, 1, 2}}	/* last element is 0? */
	    /* If the rest of the storage is initialized to 0,
	    ** note that a check would show a type of UNKNOWN.
	    */
	};
Clearer, n'est-ce pas?

Both ideas are sufficient. However, I think the latter is clearer and less
error-prone.
                      Kevin Martin, UofW Software Development Group

------------------------------------------------------
End of Vol. 2, No. 8. Std-C  (Jan. 10, 1985  07:15:00)
-- 
Orlando Sotomayor-Diaz	/AT&T Bell Laboratories, Red Hill Road
			/Middletown, New Jersey, 07748 (HR 1B 316)
Tel: 201-949-9230	/UUCP: {ihnp4, houxm}!homxa!osd7  



More information about the Mod.std.c mailing list