Loops en logica
Arnout van Kempen over rommelen in een digitale wereld.
Een paar basisvaardigheden die een programmeertaal moet hebben, de heel exotische daargelaten, zijn het herhalen van opdrachten en het voorwaardelijk uitvoeren van opdrachten. En als we toch bezig zijn, doe ik er meteen een aardigheidje van C bij dat de nauwe aansluiting met de computer laat zien: de bit-shift.
Herhalen werkt in C met drie opdrachten. De eerste is de simpelste:
while(voorwaarde){opdracht;}
Zolang voorwaarde niet nul (of false) is, wordt het opdrachtenblok dat tussen de {} staat herhaald. Als bij de start al niet aan voorwaarde wordt voldaan, wordt het opdrachtenblok dus nooit uitgevoerd.
De tweede is vrijwel hetzelfde:
do{opdracht;}while(voorwaarde);
Hier wordt het opdrachtenblok altijd een keer uitgevoerd, maar alleen herhaald zolang aan voorwaarde wordt voldaan.
Dit is nog rechttoe-rechtaan. De derde optie is "typisch C", en tegelijk een soort false-friend. Het is de for-functie, die in andere talen ook voorkomt, maar daar of een echt andere betekenis heeft of veel minder flexibiliteit kent. In Python bijvoorbeeld betekent het zoiets als "voer deze opdrachten uit voor alle elementen in een reeks", in BASIC is het een simpele teller. In C ziet het er als volgt uit:
for(initialisatie;voorwaarde;opdracht){opdracht;}
Eerst wordt initialisatie uitgevoerd, vervolgens het opdrachtenblok, dan de opdracht die als derde is gegeven en dat wordt herhaald zolang aan voorwaarde wordt voldaan. De simpelste toepassing is die van een vast aantal herhalingen, bijvoorbeeld:
int t;
for(t=0;t<10;t++){opdracht;}
maar het mag ook veel complexer en minder intuïtief wellicht. Bijvoorbeeld:
for(int x=0;key_pressed()!="q";printf("dit gaat nog wel even door\n"){}
mag ook. Hier wordt een functie aangeroepen die als uitkomst de toets geeft die wordt ingedrukt en de for-loop herhaalt zolang niet op de q wordt gedrukt. Er is geen samenhang met x en de opdracht waar je meestal de teller mee ophoogt, doet iets heel anders. En om het nog wat minder overzichtelijk te maken, de variabele x wordt pas gedeclareerd binnen de for-loop.
Naast (on)voorwaardelijke herhalingen heb je ook logische keuzes nodig. In C heb je daarvoor de if-functie en de switch. Switch heeft wat lastigheden en je moet hiervoor ook zaken als break en continue begrijpen, dus dat laat ik voor het moment. De if-functie is er in twee varianten:
if(voorwaarde){opdracht;}
if(voorwaarde){opdracht;}else{opdracht;}
Als aan voorwaarde wordt voldaan wordt het eerste opdrachtblok uitgevoerd. En als je een else toevoegt wordt het tweede blok uitgevoerd als niet aan de voorwaarde wordt voldaan. Let op, als in dat opdrachtblok de voorwaarde verandert, heeft dat geen invloed op de uitvoering. Dus in het navolgende wordt alleen het eerste blok uitgevoerd, niet het tweede:
if(x==1){x++;}else{x—;}
Het zou handig zijn als je meerdere voorwaarden kan combineren, en dat kan inderdaad. En binnen de voorwaarde zelf heb je ook nog wat variaties. Bijvoorbeeld == betekent "is gelijk", != "is ongelijk", en met || (of) en && (en) kan je combineren. Daarbij is het goed te bedenken dat C van links naar rechts evalueert tot dat niet meer zinvol is. Bij een || zal de rechter voorwaarde niet geëvalueerd worden als de linker al true is. Maakt dat dan uit? Ja toch wel. Je mag in C immers neveneffecten toevoegen, zoals met ++ en —. Op GitHub heb ik code opgenomen waar de drie loop-vormen worden uitgewerkt (let op de for-loop, daar gebeurt iets geks) en waar dit verschijnsel van stoppen met evalueren zichtbaar wordt gemaakt.
Tenslotte nog een dingetje: zoals we al zagen, zijn computers niet zo goed in reële getallen. Een computer werkt veel liever met integers, bits, bytes, words, etcetera. C sluit daar op aan door bewerkingen op bit-niveau toe te staan, die voor de computer erg voor de hand liggen. Zo kan C een shift uitvoeren. Hierbij schuiven de bits in een byte een aantal posities naar links of naar rechts. Feitelijk betekent dat vermenigvuldigen met een macht van 2 of delen door een macht van 2. Zou de computer dat moeten doen met floats, dan kost dat nogal wat rekenwerk, maar binair is het een fluitje van een cent. Ook deze shifts vind je terug in het bestandje bij deel 015 op GitHub.
Gerelateerd

De TSR en protected mode
Arnout van Kempen over rommelen in een digitale wereld.

IBM-pc en MS-DOS
Arnout van Kempen over rommelen in een digitale wereld.

Nogmaals ons programmaatje
Arnout van Kempen over rommelen in een digitale wereld.

De uitdagingen van de 8086
Arnout van Kempen over rommelen in een digitale wereld.

Programmeren van de 8080
Arnout van Kempen over rommelen in een digitale wereld.