© Harry Broeders.
Deze pagina is bestemd voor studenten van de THRijswijk groepen EPm en EPv die de module SOPX1 volgen.
In les 12 heb ik verteld dat het gebruik
van #define
met argumenten beter vervangen kan worden door een
functie. Op deze regel is (zoals op elke regel) natuurlijk wel een
uitzondering te bedenken.
Met behulp van de operator sizeof
kun je het aantal bytes van
een variabele (of van een type) bepalen.
Het onderstaande programma sizeof.c bepaalt het aantal
bytes van het type char
, het type int
, een variabele
van het type double
en een int
array van
10
elementen.
#include <stdio.h>
int main() {
double d;
int rij[10];
printf("Een variabele van het type char is %d bytes groot.\n", sizeof(char));
printf("Een variabele van het type int is %d bytes groot.\n", sizeof(int));
printf("De variabele d van het type double is %d bytes groot.\n", sizeof d);
printf("De variabele rij een array van 10 int's is %d bytes groot.\n", sizeof rij);
getchar();
return 0;
}
Op een 32 bits machine geeft dit programma het volgende resultaat:
Een variabele van het type char is 1 bytes groot. Een variabele van het type int is 4 bytes groot. De variabele d van het type double is 8 bytes groot. De variabele rij een array van 10 int's is 40 bytes groot.
Met behulp van de slimme formule sizeof rij/sizeof rij[0]
kun
je het aantal elementen van een array berekenen. Het maakt niet uit van welk
type de elementen in de array zijn! Snap je de formule?
In het onderstaande programma sizeof_rij.c wordt dit gedemonstreerd.
#include <stdio.h>
int main() {
int rij1[10];
double rij2[8];
printf("De variabele rij1 bevat %d elementen.\n", sizeof rij1/sizeof rij1[0]);
printf("De variabele rij2 bevat %d elementen.\n", sizeof rij2/sizeof rij2[0]);
getchar();
return 0;
}
De uitvoer van dit programma is als volgt:
De variabele rij1 bevat 10 elementen. De variabele rij2 bevat 8 elementen.
Het lijkt een goed idee om de formule in een functie op te nemen (dat is beter onderhoudbaar en herbruikbaar).
Het onderstaande programma sizeof_rij_functie.c geeft echter niet het verwachte resultaat:
#include <stdio.h>
/* PAS OP! Dit programma geeft reslutaten die je misschien niet verwacht */
int aantal_int(int rij[]) {
return sizeof rij/sizeof rij[0];
}
int aantal_double(double rij[]) {
return sizeof rij/sizeof rij[0];
}
int main() {
int rij1[10];
double rij2[8];
printf("De variabele rij1 bevat %d elementen.\n", aantal_int(rij1));
printf("De variabele rij2 bevat %d elementen.\n", aantal_double(rij2));
getchar();
return 0;
}
Het eerste wat opvalt is dat je voor elk type array een aparte functie moet schrijven. Begrijp je waarom? Een groter probleem is echter dat de uitvoer anders is dan je zou verwachten. Op een 32 bits machine is de uitvoer als volgt:
De variabele rij1 bevat 1 elementen. De variabele rij2 bevat 0 elementen.
Hoe is deze uitvoer te verklaren? Bij het aanroepen van een functie wordt
alleen het beginadres van de array doorgegeven. De variabele rij
die we in de functie gebruiken is dus het beginadres van de array. Op een
32 bits machine is een adres 32 bits = 4 bytes groot. De expressie sizeof
rij
levert in de functies dus altijd de waarde 4 op. In de functie
aantal_int
is rij[0]
een int en geeft sizeof
rij[0]
dus de waarde 4 (op een 32 bits machine). Het resultaat van
de functie aantal_int
is dus altijd 4/4
=
1
. In de functie aantal_double
is
rij[0]
een double en geeft sizeof rij[0]
dus de
waarde 8. Het resultaat van de functie aantal_double
is dus
altijd 4/8
= 0
.
Bij het gebruik van een #define
met een parameter is het resultaat
wel zoals verwacht en is het niet nodig om voor elk type een aparte macro
te schrijven. Dit wordt in het programma
sizeof_rij_macro.c gedemonstreerd:
#include <stdio.h>
#define aantal_elementen(rij) (sizeof (rij)/sizeof (rij)[0])
int main() {
int rij1[10];
double rij2[8];
printf("De variabele rij1 bevat %d elementen.\n", aantal_elementen(rij1));
printf("De variabele rij2 bevat %d elementen.\n", aantal_elementen(rij2));
getchar();
return 0;
}
De uitvoer van dit programma is zoals verwacht:
De variabele rij1 bevat 10 elementen. De variabele rij2 bevat 8 elementen.
De macro aantal_elementen
kun je nu bijvoorbeeld gebruiken in
het programma om de inhoud van een array om te keren dat je als extra opgave
hebt gemaakt (keerom2.c).
#include <stdio.h>
void keerom(int rij[], int aantal) {
int index;
for (index=0; index<aantal/2; ++index) {
int hulpje=rij[index];
rij[index]=rij[aantal-index-1];
rij[aantal-index-1]=hulpje;
}
}
void drukaf(int rij[], int aantal) {
int index;
for (index=0; index<aantal; ++index) {
printf("%d ", rij[index]);
}
printf("\n");
}
#define aantal_elementen(rij) (sizeof (rij)/sizeof (rij)[0])
int main() {
void keerom(int rij[], int aantal);
void drukaf(int rij[], int aantal);
int testrij1[]={12, 11, 17, 23};
int testrij2[]={12, 11, 13, 17, 23};
printf("Voor keerom:\n");
drukaf(testrij1, aantal_elementen(testrij1));
keerom(testrij1, aantal_elementen(testrij1));
printf("Na keerom:\n");
drukaf(testrij1, aantal_elementen(testrij1));
printf("Voor keerom:\n");
drukaf(testrij2, aantal_elementen(testrij2));
keerom(testrij2, aantal_elementen(testrij2));
printf("Na keerom:\n");
drukaf(testrij2, aantal_elementen(testrij2));
getchar();
return 0;
}
Een programmeur die slim denkt te zijn heeft het bovenstaande programma als volgt herschreven (keerom3.c):
#include <stdio.h>
/* PAS OP! Dit programma geeft reslutaten die je misschien niet verwacht */
#define aantal_elementen(rij) (sizeof (rij)/sizeof (rij)[0])
void keerom(int rij[]) {
int index;
int aantal=aantal_elementen(rij);
for (index=0; index<aantal/2; ++index) {
int hulpje=rij[index];
rij[index]=rij[aantal-index-1];
rij[aantal-index-1]=hulpje;
}
}
void drukaf(int rij[]) {
int index;
for (index=0; index<aantal_elementen(rij); ++index) {
printf("%d ", rij[index]);
}
printf("\n");
}
int main() {
void keerom(int rij[]);
void drukaf(int rij[]);
int testrij1[]={12, 11, 17, 23};
int testrij2[]={12, 11, 13, 17, 23};
printf("Voor keerom:\n");
drukaf(testrij1);
keerom(testrij1);
printf("Na keerom:\n");
drukaf(testrij1);
printf("Voor keerom:\n");
drukaf(testrij2);
keerom(testrij2);
printf("Na keerom:\n");
drukaf(testrij2);
getchar();
return 0;
}
De uitvoer van dit programma is anders dan de programmeur verwacht:
Voor keerom: 12 Na keerom: 12 Voor keerom: 12 Na keerom: 12
Kun jij deze slimmerik uitleggen waarom zijn programma niet werkt zoals hij verwacht?