Is it that bad to initialize global variables at outside?

V

vib

Hi there,

By chance, I came to learn that it is bad programming practice to
initialize global variables at outside of programs. Is it that bad? In
order to fullfil this, I had to declare them with const, but thereafter
they are no longer variables. Just couldn't see the benefits of this
practice. Any comments or advices are welcome.

Thanks
vib
 
P

Paul Mesken

Hi there,

By chance, I came to learn that it is bad programming practice to
initialize global variables at outside of programs. Is it that bad? In
order to fullfil this, I had to declare them with const, but thereafter
they are no longer variables. Just couldn't see the benefits of this
practice. Any comments or advices are welcome.

Global const variables are, indeed, of very little use. If you need
some constant value that can be used in your program then you should
use a #define or enum.

The book "Code Complete" (McConnel, now in its 2nd edition) lists
reasons to avoid global variables and some reasons in which they can
be handy. In general, they should be avoided if there is an
alternative.
 
K

Keith Thompson

vib said:
By chance, I came to learn that it is bad programming practice to
initialize global variables at outside of programs. Is it that bad? In
order to fullfil this, I had to declare them with const, but thereafter
they are no longer variables. Just couldn't see the benefits of this
practice. Any comments or advices are welcome.

Initializing them or not isn't really the issue. Global variables
themselves can cause problems. For example, if a function
communicates only with its caller, and only via its parameters and
return value, it's relatively easy to analyze what it does. If it
also uses global variables, it can affect, and be affected by, any
other functions that use the same global variables, even in the
absence of an explicit call. The graph of dependencies among the
various functions in your program, which would otherwise have been a
simple tree structure, becomes a bowl of spaghetti.

If you need to use global variables, go ahead and use them (just be
careful). And if you're going to declare a global variable, it
usually makes sense to initialize it, just like any other variable.
 
L

Lawrence Kirby

Global const variables are, indeed, of very little use.

They can provide information for the rest of the program.
If you need
some constant value that can be used in your program then you should
use a #define or enum.

These are simpler in a lot of cases, but other than that I don't see a
strong reason to use them in preference.
reasons to avoid global variables and some reasons in which they can
be handy. In general, they should be avoided if there is an
alternative.

The problems with global variables are much reduced if they are const.
many people would say that macros are pretty nasty, a very blunt tool
sweeping over issues of scope, namespace etc. Just because there may be an
alternative to global variables doesn't mean it is a better one.

A reasonable use of global variables can be a write once or in one place,
read anywhere approach e.g. for config data. It is a pity that C doesn't
provide an easy way to enforce this.

Lawrence
 
P

Paul Mesken

These are simpler in a lot of cases, but other than that I don't see a
strong reason to use them in preference.

One of the reasons I could think of is that an attempt to modify a
const object (indirectly) results in undefined behaviour, which may
very well turn out to be that the const object is simply modified as
if it didn't have the qualifier "const" at all. Such things have the
danger of turning into programming habits.

Also, a const is not a "constant expression" so its use is a bit more
limited in this respect (its value cannot be used in compile time).

All in all, I think that the "global const vs. #define" debate is a
bit like the "goto debate". There might be cases in which global
consts are prefered but, I suspect, not many :)
 
C

CBFalconer

Lawrence said:
.... snip ...

A reasonable use of global variables can be a write once or in one
place, read anywhere approach e.g. for config data. It is a pity
that C doesn't provide an easy way to enforce this.

Something I have been known to do:

const stuffT *thingummy(void)
{
static stuffT *data;

if (!data) {
/* code to malloc and initialize data */
}
return data;
}

Adjust nomenclature to suit.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
 
B

Ben Pfaff

Lawrence Kirby said:
A reasonable use of global variables can be a write once or in one place,
read anywhere approach e.g. for config data. It is a pity that C doesn't
provide an easy way to enforce this.

A reasonable alternative can be a function that initializes a
piece of data on its first call and returns the data or its
address on every call.
 
V

vib

const stuffT *thingummy(void)
{
static stuffT *data;

if (!data) {
/* code to malloc and initialize data */
}
return data;
}

Adjust nomenclature to suit.
I think the contents of stuffT is still changable,
let say,

typedef struct {
unsigned int myInt;
} stuffT;

main()
{
const stuffT *pMyData;
stuffT newData;

pMyData = thingummy();

newData.myInt = 10;
pMyData = (stuffT *)&newData;

...
}
 
R

robert.thorpe

CBFalconer said:
Something I have been known to do:

const stuffT *thingummy(void)
{
static stuffT *data;

if (!data) {
/* code to malloc and initialize data */
}
return data;
}

Adjust nomenclature to suit.

Another possibility is to store configuration data in a hash.
The hash can be initialized in the c file controlling config, elsewhere
the function to read from the hash is the only one exported.

This is also useful because the config file can be in the format "key .
value", making it possible to add new parameters without changing too
much code.
 
C

CBFalconer

vib said:
I think the contents of stuffT is still changable,

Please don't strip attributions of material you quote.

stuffT is a type above, not a variable. thingummy returns a
pointer to an initialized and unalterable instance of the type, and
the initialization etc. is done with code in thingummy. Nothing
except that code can get at it barring suspicious constructs (which
includes extraneous casts).


--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
 
M

Michael Wojcik

Global const variables are, indeed, of very little use.

Certainly, to people who can't think of a use for them.
If you need
some constant value that can be used in your program then you should
use a #define or enum.

If I need a constant value of structure type (probably the most common
case in my code), an enum is not suitable; prior to C99 (not available
on all the platforms I need to support), neither is a macro, and macros
aren't type-safe.

Why constant values of structure type? For initialization, of course:

struct foo { /* whatever */ };
const struct foo foo0 = {0}; /* or possibly something more complex */

struct foo *MakeFoo(void)
{
struct foo *NewFoo = malloc(sizeof *NewFoo);
if (NewFoo) *NewFoo = foo0;
return NewFoo;
}

Making gross generalizations without carefully reviewing all the
likely cases leads to posts of little value. It is often appropriate
to have a constant of aggregate type. Prior to C99, C's support for
those was limited to string literals and literal initializers.
 
P

Paul Mesken

If I need a constant value of structure type (probably the most common
case in my code), an enum is not suitable; prior to C99 (not available
on all the platforms I need to support), neither is a macro, and macros
aren't type-safe.

Why constant values of structure type? For initialization, of course:

struct foo { /* whatever */ };
const struct foo foo0 = {0}; /* or possibly something more complex */

struct foo *MakeFoo(void)
{
struct foo *NewFoo = malloc(sizeof *NewFoo);
if (NewFoo) *NewFoo = foo0;
return NewFoo;
}

Making gross generalizations without carefully reviewing all the
likely cases leads to posts of little value. It is often appropriate
to have a constant of aggregate type. Prior to C99, C's support for
those was limited to string literals and literal initializers.

You don't need a global const for that. Simply have your "initializer
struct" foo0 as a (static) const local in your function MakeFoo() and
thus "hide" foo0 behind the function MakeFoo().

Having the "initializer struct" as a global invites programmers to use
your foo0 directly. There will be two ways to initialize new foo
objects : using MakeFoo (the prefered way) and using foo0 directly
(not prefered since it makes it possible to have initialization
scattered across the code instead of having it in a single function).
 
C

CBFalconer

Another possibility is to store configuration data in a hash.
The hash can be initialized in the c file controlling config,
elsewhere the function to read from the hash is the only one
exported.

This is also useful because the config file can be in the format
"key . value", making it possible to add new parameters without
changing too much code.

You can implement that sort of thing nicely with my hashlib
package, and just export a pointer to the hshfind routine, and
pointers to the hashtables proper as created by hshinit. You will
also need a type to specify the storage. Now multiple tables
require no added code. You can find hashlib at:

<http://cbfalconer.home.att.net/download/hashlib.zip>

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
 
T

Tim Rentsch

Lawrence Kirby said:
A reasonable use of global variables can be a write once or in one place,
read anywhere approach e.g. for config data. It is a pity that C doesn't
provide an easy way to enforce this.

I've found the following technique useful:

in some_module.h:

extern const VariableType * const global_variable_pointer;
#define global_variable (*global_variable_pointer)

in some_module.c:

static VariableType static_variable;
const VariableType * const global_variable_pointer = & static_variable;


Now 'global_variable' can be used everywhere as a read-only variable,
and 'static_variable' can be written in some_module.c to change the
contents of 'global_variable'.
 
M

Michael Wojcik

You don't need a global const for that.

Obviously; removing support for global struct-type constant values
from C does not make it strictly less powerful. I don't need "while"
or "do" or "switch", either. That doesn't mean I shouldn't use them.
Simply have your "initializer
struct" foo0 as a (static) const local in your function MakeFoo() and
thus "hide" foo0 behind the function MakeFoo().

Oh, there's enlightenment: you can substitute local constants for
global ones! Who would have thought it?

Perhaps you might consider whether there are ever reasons to
preferring a global constant to one or more identical local ones.
Having the "initializer struct" as a global invites programmers to use
your foo0 directly.

It does no such thing. Programmers will do what they will do. If
they're smart, they'll use the documented interface; if not, they
won't. Exposing an implementation detail in a header (and please
note that doesn't necessarily happen in this case anyway) doesn't
make dumb programmers any smarter, or make it any harder for them to
shoot themselves in the foot.

--
Michael Wojcik (e-mail address removed)

Unfortunately, as a software professional, tradition requires me to spend New
Years Eve drinking alone, playing video games and sobbing uncontrollably.
-- Peter Johnson
 
P

Paul Mesken

Obviously; removing support for global struct-type constant values
from C does not make it strictly less powerful. I don't need "while"
or "do" or "switch", either. That doesn't mean I shouldn't use them.

Let's take "goto". It's good that C has this thing (at least, I think
so). There are situations in which "goto" can be quite handy. But it
should be used with great care (it can easily result in spaghetti code
and do even worse things). The same goes for using globals (const or
otherwise).

Reducing globals as much as possible is just a sound programming
practice. You might think it to be stupid but I've found it to be
quite efficient to adhere to.
Oh, there's enlightenment: you can substitute local constants for
global ones! Who would have thought it?

Well, you didn't since you think of a const global instead of a const
local in an initialization function to be a Good Thing (which it
isn't). If you don't want to "hide" data that should only be available
to a single function then, by all means, be my guest.
Perhaps you might consider whether there are ever reasons to
preferring a global constant to one or more identical local ones.

Your initialization function only needed a single constant, not
several.
It does no such thing. Programmers will do what they will do. If
they're smart, they'll use the documented interface; if not, they
won't.

If they're smart then they use sound programming practices.
 
M

Michael Wojcik

Let's take "goto". ...
The same goes for using globals (const or otherwise).

Insufficient warrant. There's no relationship between goto and
globals that justifies this argument.
Reducing globals as much as possible is just a sound programming
practice. You might think it to be stupid but I've found it to be
quite efficient to adhere to.

Argument by anecdote. I've seen no reason to believe your experience
(much less your reports thereof) can be usefully generalized.
Well, you didn't since you think of a const global instead of a const
local in an initialization function to be a Good Thing (which it
isn't).

And we're zero for three. Perhaps you should learn logic, Paul.
That I don't advance a certain argument does not constitute evidence
that I haven't considered it.

(I'll ignore the petitio principii and tautology, since they're only
par for the course when arguing with you.)
Your initialization function only needed a single constant, not
several.

Try considering harder.
If they're smart then they use sound programming practices.

Yes, that was rather my point. Want a cracker?
 
P

Paul Mesken

Yes, that was rather my point.

If you'd advocate sound programming practices then you wouldn't
advocate using globals where locals could have been used just as
easily.

Your example of using a const global struct for initialization was a
*bad* programming practice since it was trivial to encapsulate this
data in the initialization function, as I've shown.

Perhaps you should read a book about programming practices ("Code
Complete" is a good one).

I don't care whether you want to adhere to sound programming practices
or bad ones. But don't go advocating bad programming practices in this
group just for the sake of wanting to have an argument.
 
M

Michael Wojcik

On 13 Jun 2005 15:25:25 GMT, (e-mail address removed) (Michael Wojcik)
wrote:

If you'd advocate sound programming practices then you wouldn't
advocate using globals where locals could have been used just as
easily.

An unwarranted claim, until you demonstrate that a local variable is
always superior to a global variable, when both are available.
Your example of using a const global struct for initialization was a
*bad* programming practice since it was trivial to encapsulate this
data in the initialization function, as I've shown.

An unwarranted claim, until you demonstrate 1) an advantage to
encapsulation in this case, and 2) that such an advantage renders the
alternative "bad".
Perhaps you should read a book about programming practices ("Code
Complete" is a good one).

I've read plenty, and continue to do so.

Perhaps you should think about what you've read a bit more, since
your continual turn to cliches as absolute rules suggests cargo-
cult programming rather than critical consideration of costs and
benefits.
But don't go advocating bad programming practices in this
group just for the sake of wanting to have an argument.

Should I ever have an impulse to do so, I'll be sure to suppress it.

Now I'll ignore further posts from you on this topic unless and until
you demonstrate that you can present an actual argument, well-formed,
relevant, and topical. I won't be holding my breath.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top