Linux C Programmeren Handleiding Deel 10 – Variabele Scopes

Als je onze C programmeer leerprogramma’s serie volgt, moet je op de hoogte zijn van het concept variabelen. Terwijl we de grondbeginselen van variabelen besproken hebben, is er nog een belangrijk aspect in verband met variabelen dat we hier zullen bespreken: bereik van variabelen.

Laten we beginnen met de code voor het verwisselen van waarden die we in een van onze vorige handleidingen gebruikten:

#include <stdio.h>

void swap (int val1, int val2)
{
int temp = 0;

temp = val1;
val1 = val2;
val2 = temp;

printf("\nSwapped values are: %d and %d", val1,val2);

}

int main()
{
int a=0, b=0;

printf("Enter two integer values\n");

scanf("%d %d",&a,&b);

printf("Entered values are: %d and %d", a,b);

swap(a,b);

return 0;
}

Hier, in dit stukje code, hebben de variabelen ‘val1’ en ‘val2’ lokale reikwijdte, wat betekent dat ze tot leven komen als de functie ‘swap’ wordt aangeroepen en dat ze sterven zodra de aanroep van ‘swap’ voorbij is. Je kunt alleen geen toegang krijgen tot ‘val1’ en ‘val2’ voor of na de aanroep van functie ‘swap’. Op dezelfde manier is de reikwijdte van de variabelen ‘a’ en ‘b’ ook lokaal – lokaal aan functie ‘main’.

Merk op dat deze variabelen met lokale reikwijdte ook wel automatische variabelen genoemd worden.

Nu, terwijl variabelen met lokale reikwijdte beperkt zijn tot het blok waarin ze gedeclareerd worden, is er een andere soort variabelen waarvan de reikwijdte globaal is. Zoals de naam al zegt, kunnen variabelen met globaal bereik over functies heen gebruikt worden. Bijvoorbeeld, de variabele ‘var’ is een globale geheel getal variabele, en kan zowel in ‘main’ als in ‘swap’ functies gebruikt worden.

#include <stdio.h>

int var;

void swap (int val1, int val2)
{
int temp = 0;

temp = val1;
val1 = val2;
val2 = temp;

printf("\nSwapped values are: %d and %d", val1,val2);

}

int main()
{
int a=0, b=0;

printf("Enter two integer values\n");

scanf("%d %d",&a,&b);

printf("Entered values are: %d and %d", a,b);

swap(a,b);

return 0;
}

Standaard wordt aan globale variabelen de waarde ‘0’ toegekend. Maar dat is niet het geval met lokale variabelen – je moet er een waarde aan toekennen als ze gedefinieerd worden, anders houden ze een vuilniswaarde vast. Bijvoorbeeld in het volgende programma:

#include <stdio.h>

int var;

int main()
{
int a;

printf("Local variable 'a' currently holds: %d", a);

printf("\n Global variable var currently holds: %d", var);


return 0;
}

De kans is groot dat je een niet-nul waarde krijgt voor ‘a’. ‘var’ daarentegen zal in het begin altijd nul zijn.

Verder gaan, kunnen er globale en lokale variabelen met dezelfde naam zijn? Wel, het antwoord is ja. Ok, wat zal het volgende stukje code dan aan uitvoer opleveren:

#include <stdio.h>

int var = 5;

int main()
{
int var = 10;

printf("Local variable 'a' currently holds: %d", var);

printf("\n Global variable var currently holds: %d", var);


return 0;
}

Wel, de uitvoer zal in beide gevallen ’10’ zijn. De reden is dat de lokale variabele ‘var’ de globale ‘var’ zal overrulen. Dus nu is de volgende logische vraag, hoe krijg je in dit geval binnen ‘main’ toegang tot de globale ‘var’? Jammer genoeg is het antwoord NEE. In feite moet je voorkomen dat je in dit soort situaties terecht komt als je met de C taal werkt.

Dan komt het concept van ‘externe’ variabelen. In lekentaal: door het sleutelwoord ‘extern’ te gebruiken bij een variabele declaratie, vertel je de compiler dat deze variabele al ergens anders gedeclareerd/definieerd is en dat we hem alleen hier gebruiken. Bijvoorbeeld, in het volgende stukje code weet de compiler niet dat ‘var’ bestaat als hij probeert het printf statement binnen de hoofdfunctie te compileren.

#include <stdio.h>

int main()
{

printf("\n Global variable var currently holds: %d", var);


return 0;
}

int var = 5;

Daarom krijg je tijdens het compileren een fout als de volgende:

main.c: In function ‘main’:
main.c:14:58: error: ‘var’ undeclared (first use in this function)
printf("\n Global variable var currently holds: %d", var);
^
main.c:14:58: note: each undeclared identifier is reported only once for each function it appears in

Maar als je hier ‘var’ als extern declareert, zie je dat alles goed werkt. Dat komt omdat de compiler uiteindelijk bij de oorspronkelijke ‘var’ declaratie komt.

#include <stdio.h>

int main()
{
extern int var;

printf("\n Global variable var currently holds: %d", var);


return 0;
}

int var = 5;

En je krijgt de juiste uitvoer:

Global variable var currently holds: 5

Dit is dus hoe extern werkt. Extern variabelen worden vaak gebruikt als je programma/project over meerdere broncode bestanden verdeeld is en je, zeg maar, in ‘bestand1’ een variabele wilt gebruiken die in ‘bestand2’ gedefinieerd is.

En tenslotte, nu we het toch over variabele scopes hebben, is het beter dat we hier ook ‘statische’ variabelen bespreken. Statische variabelen zijn bijzonder in die zin dat ze hun waarde behouden, ook nadat ze buiten scope gaan. Dit betekent dat ze maar één keer geïnitialiseerd worden, en dat is de eerste keer.

static int counter 

Hieronder volgt een stukje code dat een statische variabele gebruikt om het aantal keren te tellen dat een functie wordt aangeroepen.

#include <stdio.h>

int swap (int val1, int val2)
{
static int counter = 1;
int temp = 0;

temp = val1;
val1 = val2;
val2 = temp;

printf("\n Function called %d times\n", counter);
counter++;
}

int main()
{
int a=9, b=4;

swap(a,b);
swap(a,b);
swap(a,b);

return 0;
}

Hier zie je de uitvoer:

 Function called 1 times 

Function called 2 times

Function called 3 times

Zo zie je dat de variabele ’teller’ zijn waarde behield, ook nadat hij buiten scope ging. Net als globale variabelen hebben ook statische variabelen een standaardwaarde van ‘0’.

Conclusie

In deze handleiding bespraken we verschillende belangrijke begrippen, die allemaal te maken hebben met de reikwijdte van variabelen in de programmeertaal C. Vergeet niet je eigen programma’s te maken om het verschil tussen externe, statische, globale en lokale variabelen beter te begrijpen. En zoals altijd, als je twijfels of vragen hebt, stuur dan een commentaar hieronder.