#Klooienmetcomputers

C

Arnout van Kempen over rommelen in een digitale wereld.

Waar veel programmeertalen werken met 'een programma' waarin eventueel sub-programma's, routines, of functies aangeroepen kunnen worden, is in C het programma zelf een functie. Commando's die je gebruikt? In principe ook functies. En dat betekent dat de basisvorm van zowel je programma als van commando's veelal hetzelfde is: de naam van de functie, argumenten tussen haakjes, en de functie kan een waarde opleveren. Als je zelf functies schrijft, zal je willen coderen wat de functie doet. Deze code plaats je tussen { en }, en functies en eventueel andere opdrachten houd je gescheiden door ;

De naam van de functie die je programma IS, is altijd main. En de uitkomst van main is een waarde die het programma terug zal geven aan het operating system waarop je je programma uitvoert. Gewoonte is hiermee een foutcode mee te geven, waarbij 0 staat voor foutloos, en andere waarden kan je zelf definiëren. Hierdoor kan je bijvoorbeeld een programma “Hallo” aanroepen in de shell, en meteen testen op de correcte werking. Bijvoorbeeld in  de standaard shell van Pi OS, de bash-shell, zou je dan zoiets kunnen doen als

if [Hallo -eq 0] then echo dat ging goed

Hiermee wordt je programma Hallo uitgevoerd, en als het goed ging krijg je te horen dat het goed ging. Maar terug naar C.

Als je programma main heet en een functie is, dan zal je die een type mee moeten geven, bij voorkeur int. Als je geen resultaat wil meegeven, kan void ook, maar dat is dus wat minder netjes. Verder moet je argumenten benoemen in de functiedefinitie. Die argumenten krijgt je programma ook weer mee vanuit het operating system, maar je kan er ook voor kiezen geen argumenten te gebruiken. In dat geval benoem je de argumenten als void, of je benoemt ze helemaal niet. De volgende definities zijn dus allemaal bruikbaar, waarbij de eerste zowel netjes als kort is:

int main(){return 0;}
int main(void){return 0;}
void main(){}
void main(void){}

Let op, bij de eerste twee moet een return waarde worden gegeven, bij de laatste twee niet, aangezien de laatste twee als type void hebben meegekregen.

De accolades gaan nog veel gebruikt worden, en je krijgt accolades binnen accolades, dus het is handig om het overzicht te bewaren. Dat doe je door bij elkaar horende accolades in dezelfde kolom te zetten, en na een accolade altijd in te springen. Geany, Runestone en nano doen dat allemaal automatisch, en zo niet dan kan je dat standaard alsnog aanzetten. Afhankelijk van je code-editor krijg je ook nog handige voorzieningen als code-herkenning (soorten code krijgen automatisch een kleur om de leesbaarheid te vergroten), automatisch sluiten van code-blokken en dergelijke, en code-completion. Gewoon proberen, dat blijkt vanzelf en dan kan je bekijken wat je handig vindt werken.

Als je functies gaat schrijven moet je er in C altijd rekening mee houden dat de variabelen die je gebruikt niet overal dezelfde betekenis hebben. Om te beginnen een simpel voorbeeld waar nog niets spannends aan de hand lijkt:

#include<stdio.h> //header file die je altijd wel nodig hebt

/* eerst een functie die twee integers optelt.

Het resultaat wordt als uitkomst van de functie terug gegeven */

int tel_op(int a, int b)
{
     int r = a+b;
     return r;
}

int main()
{
     int a = 10;
     int b = 20;
     int som;
     som = tel_op(a,b);
     printf("De som van %d en %d is %d\n", a, b, som);
     return 0;
}

Compileer dit, en run het, en je krijgt de correcte uitkomst te zien.

Toch zit hier al een paar bijzonderheden in om op te wijzen. Natuurlijk de manier waarop de printf() functie variabelen in een tekst verwerkt en het feit dat je variabelen zowel met een beginwaarde als zonder beginwaarde kan declareren.

Maar in dit programmaatje is de naamgeving van de variabelen in de functie tel_op onverstandig gekozen. De a en b in tel_op() zijn namelijk NIET de a en b uit main(). Ze mogen dezelfde naam hebben, omdat ze in verschillende functies worden gedeclareerd, maar omdat ze feitelijk verschillend zijn is het handiger ze ook verschillende namen te geven.

Los daarvan is een naam als "som" of "tel_op" net wat duidelijker dan "a" of "b". In een wat groter programma waar je langer aan werkt, is het slimmer namen te kiezen die ook nog betekenis hebben als je er een maand later weer eens naar kijkt.

Verder mag je de volgorde van functies omdraaien, dus beginnen met main() en daarna pas tel_op() schrijven, maar de compiler geeft je dan wel een waarschuwing dat je de functie aanroept voordat je deze definieert. Niet erg, wel net iets slordiger.

Tenslotte nog een ding: C staat extreem compact coderen toe, maar het komt de leesbaarheid niet altijd ten goede. In dit geval zal het niet zoveel uitmaken, maar bedenk dat

int r = a+b;

net iets minder leesbaar is dan

int r;
r = a+b;

maar leesbaarder is dan

return a+b;

Liefhebbers van netjes programmeren zullen sneller kiezen voor de meest leesbare vorm; persoonlijk vind ik het vooral een kwestie van smaak. Het gebruik van toelichting, spaties, inspringen, etcetera: ook allemaal een kwestie van smaak. Maar bedenk dat het hiervoor gegeven programmaatje exact hetzelfde doet als

#include<stdio.h>
int t(int a,int b){return a+b;}
void main(){int a=10,b=20;printf("De som van %d en %d is %d\n",a,b,t(a,b));}

Gebruik GitHub om te klooien met de computer!

Wie mee wil doen met #klooienmetcomputers, maar niet alle teksten van Arnout wil overtypen, of de eigen code wil delen met andere lezers, kan dat doen via GitHub:

1. Maak een account op www.github.com

2. Zoek naar Abmvk/kmc

Het account Abmvk volgen kan ook.

Arnout plaatst daar alle stukjes code voor #klooienmetcomputers, met als naam eerst een volgnummer van het stukje waar de code bij hoort en dan een term uit de titel. Zaken die bijvoorbeeld in een config-bestand thuishoren plaatst hij als .txt bestand, wat overtypen kan besparen. Ook plaatst hij stukjes code waar hij zelf mee rommelt en die niet in een stukje op accountant.nl terechtkomen. Die stukjes zijn te herkennen omdat er geen volgnummer voor staat.

Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren. Samen kom je een eind. Om dit goed te laten werken: maak een clone van Arnout’s repo, haal met pull nieuwe bestanden binnen en voeg met push zelf toe. Wie er niet uitkomt: laat het Arnout weten.

Arnout van Kempen di CCO CISA is Senior manager Risk & Compliance bij Baker Tilly. Hij schrijft op persoonlijke titel. Hij is lid van de Commissie Financiële verslaggeving & Accountancy van de AFM en lid van de signaleringsraad van de NBA. Daarnaast is hij diaken van het bisdom 's-Hertogenbosch.

Gerelateerd

reacties

Reageren op een artikel kan tot drie maanden na plaatsing. Reageren op dit artikel is daarom niet meer mogelijk.

Aanmelden nieuwsbrief

Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.