Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!godot!harvard!seismo!brl-tgr!gwyn From: gwyn@brl-tgr.ARPA (Doug Gwyn ) Newsgroups: net.lang.c Subject: Re: Diatribe on uninitialized externs Message-ID: <5563@brl-tgr.ARPA> Date: Thu, 1-Nov-84 23:03:44 EST Article-I.D.: brl-tgr.5563 Posted: Thu Nov 1 23:03:44 1984 Date-Received: Sat, 3-Nov-84 07:56:13 EST References: <9572@watmath.UUCP> <5494@brl-tgr.ARPA> <9633@watmath.UUCP> Organization: Ballistic Research Lab Lines: 104 > >... The last explict initializer is repeated as necessary > >to fill out the array. > Oh yeah? Since when? k&r appendix A section 8.6 paragraph #5 says missing > items get zeroed. Well, I tried this on a UNIX System V PCC and what Kevin says does describe its behavior. I wonder where I got the other idea (which I suggest is a better rule, but incompatible with current behavior). > ... Besides, who says I always want the same variant of the union > initialized. What if one array uses the 'int' element (so I want int zeros), > and another array uses the pointer element (so I want NULL's)? In many years of C programming I have never had such a requirement. Unions are pretty much a kludge for things like memory allocation. I can think of a general way to specify this type of initialization: union { int a; double b; char *c; } foo = { , 3.14159, }; using explictly empty members in the initializer (this would apply to structs as well as unions). The only incompatibility with current C that I see here is the slightly different meaning of the final , in the initializer list. This solution avoids the ambiguity of using just a type specifier (which would work for unions but not for structs) and having to supply explicit member names for initializers (which calls for a significant change to existing compilers). > >> The programmer cannot signal to the reader that a variable is > >> deliberately being left un-initialized. > >Sure he can. Nothing prevents you from specifying initializers you care > >about and letting the rest default. I do this anyway. > I agree, he can signal deliberately *initialized* ones. But given a declaration > like > int x; > I can't tell if he really cares that there is a zero there, if he forgot > to initialize it, or if he doesn't care what is in it... Unless you outlaw int x; altogether, or require that there be an explicit initializer SOMEWHERE among all the load modules (`a la Whitesmiths), you still won't be able to tell if he wanted the default initialization according to the rules (assuming a "non-junk" rule), if he doesn't care, or if he forgot. Using the same method I suggested above for struct/unions, int x = { }; is an explicitly empty initialization showing that the programmer has thought about the matter and decided that he didn't care what's there. > The language should not make the "overlay system designer"'s job impossible. > The language spec doesn't even have to mention overlays. It merely has to > say what happens to un-initialized variables. I agree that something definite should be said about the initial contents of un-initialized variables. If an overlay system designer finds that there is no practical way of avoiding clobbering variables (by reloading their initial values), then he has to give up the idea of transparent overlay facilities, since it is clear that non-auto/register variables are intended to retain whatever is stored into them until the program explicitly stores something else there. This is perfectly reasonable and any violation needs to be announced loudly to the user of that particular overlay system (which should not get in the way when the user elects NOT to use overlays). Very few overlay systems (including the one Ron Natalie and I did for JHU/BRL PDP-11 UNIX) are COMPLETELY transparent at the source code level, although that is certainly a desirable goal. > Bear in mind that I use such hostile machines in my regular work, and > have encountered no problems with the current rules (other than not > being able to tell deliberate un-initialized from deliberate but implicit > zero, a problem which is not solved by typed-zero initialization). If the rule is that uninitialized data is filled with proper-typed zero, then it seems that you wouldn't have to care which was intended (since the value of deliberately un-initialized "don't care" storage cannot be correctly used until it is stored into). The problems would appear to be due to trying to follow different rules, for example using specially- tagged "illegal data" values or "not defined" memory manager traps for uninitialized data instead of zero. By the way, I think we should beat on the hardware designers who keep dreaming up these "helpful" features without checking with compiler/OS implementers to see what their effects will be. If possible, buy more reasonable hardware and TELL the loser of the competition just what's wrong with his fancy design. The reason for zero bit pattern is clearly because that is what UNIX does automatically for "bss" storage. Not all OSes allow one to use tricks like this, although the C runtime startoff module could be a fast loop to initialize "bss" to a zero bit pattern. Typed zero, though, in general would have to be initialized by the compiler or by a rather smart link editor (I can think of some other, incredibly ugly, kludges). I think I will modify my position: IF uninitialized data HAS to have some valid value, then I would (still) recommend 0 of the appropriate type rather than a 0 bit pattern. This seems to be compatible with currently portable C code. However, if one is willing to drop the compatibility requirement (apparently the ANSI committee is not), then I would have uninitialized data contents UNKNOWN, possibly trap-causing, if they are used before being defined. That would help stamp out sloppy coding practices (nothing will completely solve this problem).