Tak jak wcześniej napisałem opiszę swoje doświadczenia z korzystaniem ze zmiennych globalnie dostępnych.
Jeżeli planujemy pisać dłuższe programy dobrze jest wyrobić sobie odpowiednie nawyki. Jednym z nich jest rozważne używanie zmiennych globalnych. To co mnie dziwi w przykładach dawanych na wykładach jest wykorzystywanie do wszystkiego zmiennych globalnych.
Weźmy na przykład jeden z projektów na ćwiczenia z programowania. Napisać stos przechowujący elementy dowolnego typu.
Według podejścia “wykładowego” w programie takim pojawiłaby się zmienna globalna np.
struct {
int pole1;
int pole2;
[...]
} stack;
int stackPop(void *elem){
/* coś tam pobierającego, wybierającego i usuwającego */
elem = lastElement
return 0;
}
int stackPush(void *elem, size_t size){
/* dodawanie */
return 0;
}
int main(int argc, char **argv){
/* tutaj może jakaś inicjalizacja by się pojawiła */
stackPush(to_add, sizeof(to_add));
if(stackPop(getEelem) == 0){
free(getEelem);
}
return 0;
}
Teraz wyobraźmy sobie, że przydałoby się w tym samym albo w innym programie stworzyć kilka stosów. Ale jak to zrobić jeżeli funkcje korzystają wprost ze zmiennej globalnej? Ano trzeba wszystko przeedytować na to jak można było na samym początku napisać:
struct stack_struct {
int pole1;
int pole2;
[...]
};
int stackPop(struct stack_struct *stack, void *elem){
/* coś tam pobierającego, wybierającego i usuwającego */
elem = lastElement;
return 0;
}
int stackPush(struct stack_struct *stack, void *elem){
/* dodawanie */
return 0;
}
int main(int argc, char **argv){
/* tutaj może jakaś inicjalizacja by się pojawiła */
stackPush(stack1, to_add1, sizeof(to_add1));
stackPush(stack1, to_add2, sizeof(to_add2));
stackPush(stack2, to_add3, sizeof(to_add3));
if(stackPop(stack1, getEelem) == 0){
free(getEelem);
}
return 0;
}
Używanie zmiennych globalnych naprawdę bardzo sporadycznie jest przydatne, a jeszcze rzadziej jest potrzebne.
Jeszcze jedna różnica z wykładowymi programami to tak, że ja nie używam typedef’ów. Jedno co moge o takowych powiedzieć to to, że tworzenie typów wskaźnikowych jest głupotą/masochizmem. A jedyna różnica o jakiej wiem pomiędzy
typedef struct {
[...]
} aaa;
a
struct aaa {
[...]
};
jest przyzwyczajenie. Dla mnie czytelniejszy i wygodniejszy jest drugi zapis. Choć może typedef ma jeszcze jakieś ukryte właściwości, o których nie było mi dane do tej pory się dowiedzieć.