Global variables considered harmful?
leichterj at dec-rani.UUCP
leichterj at dec-rani.UUCP
Tue Jun 12 05:00:14 AEST 1984
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
More information about the Comp.unix.wizards
mailing list