hokey@plus5.UUCP (Hokey) (10/23/84)
I asked why unions were initialized using the first element, and received this reply: > From: wucs!seismo!harvard!wjh12!kendall > To: plus5!hokey > Subject: ANSI initialization of unions > References: <504@plus5.UUCP> > > The ANSI C rule for initialization of unions (use the first member) > is there because there is no syntax for indicating which member of a > union you want to initialize. > > Sam Kendall {allegra,ihnp4,ima,amd}!wjh12!kendall > Delft Consulting Corp. decvax!genrad!wjh12!kendall My point is, it doesn't matter. 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. Note that there is no ambiguity even when initializing a list of items inside a union: the initializer-list could be cast, or the first element of the list could be cast. The following is *not* a well-thought-out example. Please bear with me: #define CHAR 01 #define SHORT 02 #define LONG 03 #define FLOAT 04 #define DOUBLE 05 #define SHORT_A 06 struct { /* I know it doesn't have a name */ int CellType; /* holds one of the above defines */ union { char cv_char; short cv_short; long cv_long; float cv_float; double cv_double; short cv_short_a[4] } cv; } cell[10] = { /*0*/ {CHAR, '?'}, /* cast isn't needed in this case */ /*1*/ {DOUBLE, (double)2}, /*2*/ {SHORT_A, (short[]){0, 1, 2}} /* last element is 0? */ }; Shoot away! (This is the sort of thing I'd like to discuss in mod.std.c) -- Hokey ..ihnp4!plus5!hokey 314-725-9492
hokey@plus5.UUCP (Hokey) (10/24/84)
> < Note that there is no ambiguity even when initializing a list of items > < inside a union: the initializer-list could be cast, or the first element > < of the list could be cast. > > Dennis himself pointed out immediately this example when given the above > argument a year and a half ago at a standards meeting: > > union { > char *x; > char y[4]; > } = "abc"; > > The string "abc" can represent either a character string to initialize the > array y or it can represent a character pointer to represent the pointer x, > depending on the context. Considering that both contexts are valid in this > place, some rule is necessary. The rule of "first listed in the union" > would mean that it would initialize the pointer. If you wanted the array > initialized, how would you specify it with casts? There is no way currently, > but it is easy to do with ANSI C by just listing the array first. > > Tony Hansen > pegasus!hansen So cast it. (No hidden pun...) Use this instead: union { char *x; char y[4]; } Strange[] = { (char[]) "abc", /* This is an array of characters (y) */ (char *) "abc" /* This is a pointer to a character */ }; Did you read the last comment above? All (char *) does is "permit" one to reference the object to which it points *as a character*. There is no guarantee regarding the veracity of the object "at the end of the rainbow" or the objects surrounding the item referenced by the pointer. Do I need to go on about this point? As near as I can tell, initialization of tables is the biggest pain. These tables need to be initialized to useful data. I would hate to see a portion of a table initialized at compile time and the rest of it initialized at run time! I, for one, would rarely bother to initialize unions at compile time because I almost always want the union portions of the tables filled with data befitting the table entry. The proposed initialization rule seems weak to me. Both replies to my posting were cases where there was an ambiguity in the interpretation of the initializer (the other reply asked about the case in which a union of an int and a float was initialized to "2"). I am one of those apparently rare people who explicitly declares or casts Everything. (Well, almost. I usually specify the "length" to malloc, read, and write using an int because I never let the data lengths get that big; the data in these cases is invariably string, and all the string functions use ints.) I wish the C compiler would help people like me, and warn me about implicit declarations and conversions. I don't care if I have to add a switch to CFLAGS (although I would prefer strict checking as the default, and make the lazy people specify a switch to provide "lax" checking). Explicit declarations seem to solve the problem of arbitrary initialization of unions. Could somebody point out an example where casting initializers won't work? -- Hokey ..ihnp4!plus5!hokey 314-725-9492