Sunil said:
Hi all,
I want to know how good or bad it is using global variables i.e
advantages
and disadvantages of using global variables.
Sunil.
File-scope (global) variables are rarely as useful as they seem, and
should be avoided.
The only reasonable time to use a global variable is when you need to
preserve state between function calls without exposing that information
to the caller. For example, take this simple stack module:
/* stack.c */
#define STACKSIZE 128
/**
* The static keyword is only there to
* prevent these symbols from being exported
* by the linker; the objects have static extent
* by virtue of being declared at file scope.
*/
static size_t stackPointer;
static int stack[STACKSIZE];
void Reset()
{
stackPointer = STACKSIZE;
}
void Push(int value)
{
if (stackPointer > 0)
stack[--stackPointer] = value;
else
/* handle overflow error */
}
int Pop()
{
int val;
if (stackPointer < STACKSIZE)
val = stack[stackPointer++];
else
/* handle underflow error */
}
int Top()
{
return stack[stackPointer];
}
In this example, the stack and stackPointer are used to keep track of
the stack contents between calls to Reset(), Push(), Pop(), and Top(),
and the stack user cannot manipulate these items directly.
This approach has several drawbacks, though. For one thing, you can't
create multiple stacks, since you only have one instance of stack data.
Secondly, and more importantly, it leads to maintenance headaches by
tightly coupling functions; in other words, changing the logic of one
function may have an unintended effect elsewhere if you change how the
global is manipulated. It can also make testing and debugging more
difficult.
If you need to preserve state, but don't want to expose that
information to whoever's using your module, you can hide it behind a
pointer to an incomplete type definition, like so:
/* stack.h */
#ifndef STACK_H
#define STACK_H
/**
* create a pointer to an incomplete type; this way,
* the use of the module can pass the pointer around, but
* cannot access the members of the struct through the pointer.
*/
struct stackData;
typedef struct stackData *stack_t;
/**
* Since the user of the module can only refer to a pointer
* to a stack, we need a way for him or her to create a new
* stack instance. NewStack() will dynamically create an
* instance of struct stackData and return the pointer to it.
*/
stack_t NewStack(size_t stackSize);
void Reset(stack_t stack);
void Push(stack_t stack, int value);
int Pop(stack_t stack);
int Top(stack_t stack);
/**
* Since we're dynamically allocating stacks, we need a way
* to release them as well.
*/
void DestroyStack(stack_t *stack);
#endif
/* stack.c */
#include <stdlib.h>
#include "stack.h"
/**
* Complete the struct type definition
*/
struct stackData {
size_t stackSize;
size_t stackptr;
int *stack;
} stackData_t;
/**
* Implement the functions, using the stack parameter.
* This is left as an exercise for the reader.
*/