[comp.lang.c] On global variables

bill@twwells.uucp (T. William Wells) (04/18/89)

My own solution to the problem of globals is this:

State variables, ones which map fairly obviously into the current
processing state of a program subsystem, should be globals. Note this
is "should", not "may". Variables which are dependent on local context
should be function parameters. Variables which are intermediate may
be either globals or function parameters, with clarity and efficiency
(and sometimes the quirks of C) determining which. When a given
subsystem is small (e.g., a function or two), parameters should
generally be used, though there are times when globals are more
appropriate.

As an example: I tend to have to write complex systems which operate
with control structures that contains lots of data. It would be
costly to pass the address of the control structure (about 10% in
space and execution time, I often write small functions) to all the
routines in the system and wouldn't add one bit to program clarity;
what I do is have the system interface routines store the address of
the structure as a global and have each routine which needs it use it.
In this case, an obvious part of the operating state is the current
context the system is operating in, thus that current context should
be a global.

Another example of a state variable is the program parameter,
typically set at the start of the program and never changed
thereafter, or only changed on user request. Again, this often maps
directly and obviously into the current program state and thus should
be global.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

ark@alice.UUCP (Andrew Koenig) (04/18/89)

In article <826@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes:

> My own solution to the problem of globals is this:

> State variables, ones which map fairly obviously into the current
> processing state of a program subsystem, should be globals.

Suppose you have some kind of transaction processing system with
a menu-oriented user interface.  The state of the screen is presumably
one of these `state variables' you mention.

Now someone comes along and tells you to rework your system to
allow split screens -- that is, multiple transactions on one
physical screen.  Presto!  You have just been forced to rework
your design to distinguish between logical and physical screens
and to know which logical screen you're working on, and how the
state of the logical screen relates to the state of other things
in your program you must now replicate, and so on.

Thus even in `obvious' cases like this, it may sometimes pay off
to put things that look at first as if they should be global
into a structure of some kind whose address is passed around
to every function that needs those entities.

Of course, this is a pain; hence many people don't do it.
It would be nice if C had some kind of facility for passing
stuff of this kind around implicitly so you didn't have to
write an extra argument for every function and every reference
to `global' data.

Now you know one of the reasons C++ works the way it does.
-- 
				--Andrew Koenig
				  ark@europa.att.com

bill@twwells.uucp (T. William Wells) (04/19/89)

In article <9215@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
: In article <826@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes:
:
: > My own solution to the problem of globals is this:
:
: > State variables, ones which map fairly obviously into the current
: > processing state of a program subsystem, should be globals.
:
: Suppose you have some kind of transaction processing system with
: a menu-oriented user interface.  The state of the screen is presumably
: one of these `state variables' you mention.

Yes. Sort of. It depends on how you think of the program.

: Now someone comes along and tells you to rework your system to
: allow split screens -- that is, multiple transactions on one
: physical screen.  Presto!  You have just been forced to rework
: your design to distinguish between logical and physical screens
: and to know which logical screen you're working on, and how the
: state of the logical screen relates to the state of other things
: in your program you must now replicate, and so on.

You've criticised the wrong thing.

If the program was designed to handle only one screen, it is
irrelevant whether you passed the variables as parameters or stored
them as globals: it's going to be a bitch to rework your program to
make it deal with multiple windows. (Ask me, I know! :-)

But, if you had considered the possibility that the program would
have to deal with multiple windows, you'd have grouped the window
parameters in one place and kept them separate from the screen
parameters. Then, all you'd have to do is put the window parameters
into a structure, make a pointer to the current window one of the
globals, modify the references to the erstwhile globals, and modify
the necessary code to correlate the screen parameters and the window
parameters, e.g., the window switching code and cursor positioning
code.

: Thus even in `obvious' cases like this, it may sometimes pay off
: to put things that look at first as if they should be global
: into a structure of some kind whose address is passed around
: to every function that needs those entities.

Well, I'd agree that it might be a good idea to put all the stuff
into a structure; that can make life easier, not to mention
encouraging encapsulation of the data. But it still doesn't deal with
the question of whether the structure (or pointer) should be a global
or a parameter.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)