Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site decwrl.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!houxm!houxz!vax135!floyd!cmcl2!seismo!hao!hplabs!sdcrdcf!sdcsvax!dcdwest!ittvax!decvax!decwrl!dec-rhea!dec-rani!leichterj From: leichterj@dec-rani.UUCP Newsgroups: net.unix-wizards Subject: Global variables considered harmful? Message-ID: <1363@decwrl.UUCP> Date: Mon, 11-Jun-84 15:00:14 EDT Article-I.D.: decwrl.1363 Posted: Mon Jun 11 15:00:14 1984 Date-Received: Wed, 13-Jun-84 02:34:56 EDT Organization: DEC Engineering Network Lines: 76 The "well structured" approach [to "exorcising externs"] would be to define a small module (aka package) with entry points as follows: void seterrno(i) int i; /* called by system routines to record an error number */ int geterrno() /* returns the last parameter to seterrno, 0 if none */ Now you do your system calls as follows: if (open(...) == -1) { printf("open error %d\n", geterrno()); } Presto, no externals, just a single static within the errno module. This would make a lot more sense if the loader supported more than just a flat global name space, a la Modula II. -- Andrew Klossner (decvax!tektronix!orca!andrew) [UUCP] Ah, yes, religion strikes again. In what what way is a an externally-known integer - "errno" - inherently worse than an externally-known function like "seterrno"? To put it another way: In what way is there any difference between the se- mantics defined by seterrno()/geterrno() - i.e. the ability to set and read a single integer value - and the semantics defined by a externally-known integer variable errno, which can be set and read? How about the following: #define geterrno() (errno) #define seterrno(x) (errno = x) Structured? Unstructured? How about: #define ERRNO_LOC (&errno) and then define set() and get() so that set(addr,val) is *addr = val, and get(addr) is *addr (as macros or functions, as you prefer). The "addr" is supposed to be something of the form xxx_LOC; you can even make up a typedef so that lint will complain about anything else in that position. Structured? Unstructured? The PROBLEM with using externals is that they make it easy to provide deep hooks into the inards of packages, leading to a very baroque and complex interface. This is what should be avoided. Avoiding externals, however, does not guarantee clear code any more than avoiding gotos does; anything I can do with a external, I can as easily do with the getxxx()/setxxx() paradigm, and the resulting code is no more or less structured than the original code was. There are no "royal roads" to well-structured, well-written code. -- Jerry PS: There is ONE difference - which CAN be significant - between an external- ly-known errno and the geterrno()/seterrno() pair: In debugging, I can easily change seterrno() to record all changes to errno, for example, while it is a bit harder to watch for all attempts to set errno. This has nothing to do with program structure; it has everything to do with debugging environments. If I want to maintain restrictions on what can go into errno - say, non-nega- tive integers only - then again using seterrno() might be a good technique in C; but I'd rather have a compiler than understood assertions of Boolean condi- tions on variables - #assert errno (errno >= 0) might be the syntax - and then inserted the appropriate check code - probably by synthesizing a function like the seterrno() I'd otherwise write. (The linker might have to help out.) This approach would be much closer to the way I want to think about the problem, and would work as well for local and static variables as for extern's. -- J