Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!gatech!purdue!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Help, page 197 K&R !!! Message-ID: <18350@mimsy.UUCP> Date: 1 Jul 89 20:00:04 GMT References: <646@kl-cs.UUCP> <648@kl-cs.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 107 >>In article <646@kl-cs.UUCP> atula@cs.keele.ac.uk (Atula Herath) asks: >>>Could somebody please explain me [paragraph 7, p.197 of K&R-1] >In article <648@kl-cs.UUCP> pc@cs.keele.ac.uk (Phil Cornes) writes: >>K&R C says that member names in structures and unions must (in general) be >>unique. This is because in early implementations the names of structure and >>union members were not associated with their parent names but were only stored >>as a type and offset from the start of the parent. This is correct. These early implementations had all but vanished by the time K&R 1st ed. started selling, and the note in the appendix was rather more harm than help. In article cline@sun.soe.clarkson.edu (Marshall Cline) writes: >Another reason: K&R C (and ANSI[??] -- I don't know) allow[ed|s] a pointer >to be implicitly cast to a pointer-to-struct if the appropriate "->field" >was given. This is no longer true. PCC accepted the `old' construct but with a warning (or a fatal error if the member name was not unique). Some PCCs no longer accept these ever. As I explained not long ago in this very same newsgroup, once upon a time C had no unions. Instead of struct symbol { char *sym_name; int sym_type; /* one of SYM_INT or SYM_FLOAT */ union { int su_int; float su_float; } sym_un; }; ... struct symbol *p = ...; if (p->sym_type == SYM_INT) ival = p->sym_un.su_int; else fval = p->sym_un.su_float; ... one wrote struct symbol { char *sym_name; int sym_type; /* SYM_INT */ int sym_int; }; struct fsymbol { char *sym_name; int sym_type; /* SYM_FLOAT */ float sym_float; }; ... struct symbol *p = ...; if (p->sym_type == SYM_INT) ival = p->sym_int; else fval = p->sym_float; ... >Something like the following: > > typedef struct {int squiggle, wiggle;} worm_t; > main() > { char *p; > ... > p->squiggle = 3; /* implicit cast of "p" to "(worm_t *)p" */ > ... > } This was allowed in the same pre-union days, but only as a side effect of never looking at both the left and right sides of the `->' operator at the same time. The compiler treated `->' as fetch offset via rhs value add offset to lhs value load word (size determined by rhs type) from pointer result and, since all pointers were the same size as an int---after all, the language only ran on PDP-11s, not IBM PCs with mixed models or the like---the only requirement was that the lhs not be floating point. (`long' did not exist then.) One could and did legitimately write such things as 0777440->csr |= RK_GO; /* start the disk */ It did not take long for this approach to be discarded. (But, surprise surprise, it still works in the 4BSD compiler. Of course, you have to use 0x20100000+0777440 on a VAX-11/780.) >I personally have never used this, as it seems left over from the days when >typedef's were discouraged (what some call "Classic C"). It is left over from days much further agone. Like Classic Coke, Classic C had a number of formulations. This little bit of type-ignorance is akin to the cocaine in Coca-Cola, not the sugar. (Coke dropped the cocaine content in the early 1900s, and switched from `cane sugar' to `cane sugar or corn syrup, whichever is cheaper' in the late 1900s. But they only changed the *amount* of sugar recently, when New Coke appeared.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris