De programmeertaal 'C' en 'C++'

programmeertaal cDeze pagina gaat over mijn oude liefde, de programmeertaal C. Ik leerde de taal C kennen in 1986 door het werk wat is toen deed. Ik was programmeur van embedded software en schreef hoofdzakelijk in Z80 assembler code maar langzaam ging dit steeds meer richting C. De taal C is ook maar één stap hoger dat assembler dus het was ook een logische stap. Naderhand ben ik ook PC applicaties gaan schrijven in C en er was zelfs een tijd dat ik de compiler als rekenmachine gebruikte. Na het lezen van de C bijbel, het bekende witte boekje van Kernighan en Ritchie was ik een totale fan van de programmeertaal C. Samen met de collega's probeerden we steeds meer geavanceerde dingen te doen en werd het schrijven van code in C een soort van kunst. We probeerden steeds beter te worden en steeds mooiere en meer efficiënte code te schrijven. Uiteindelijk heb ik een compleet datacommunicatie pakket "mightycom" in C geschreven met vele terminal emulaties, allerlei download protocollen, data compressie layers als MNP en zelfs een eigen script interpreter en TCP/IP stack.

We leverden onze eigen tekstverwerker, onze eigen installers en collega's schreven zelfs in C en compleet eigen besturingsysteem. Voor Sony hebben we een compleet office pakket geschreven voor de MSX ook geheel in de taal C. Ook schreef ik complete command interpreters, protocol stacks zoals mnp, v42bis en adpcm compressie software voor de roms van modems die we ontwikkelden en zelfs een complete tiny basic interpreter. In de jaren daarna heb ik in C (inmiddels ook C++) geprogrammeerd op Digital VMS machines, op Unix systemen, op Sun solaris systemen en op IBM Pc's onder Microsoft Windows. Het hoogtepunt van mijn C++ tijd was dat ik een half jaar moest meeprogrammeren met het ontwikkelteam van Psion in Londen, waar ik de GSM protocol stacks gemaakt heb voor Epoc32, het latere symbian besturing systeem dat geheel in C++ geschreven is. Naast de taal C heb ik in bijna elke andere taal geprogrammeerd, maar de taal C en "C++" zijn nog steeds mijn grote (oude) liefde. Meer over C++ kunt u vinden op mijn C++ pagina.

In mijn vrije tijd schreef ik grafische demo's en spelletjes en ik heb zelf een tijd 3D programma's geprogrammeerd, wanneer het op snelheid en efficiënte code aankomt, is er nog geen enkele andere programmeertaal die de taal C kan verslaan. Toen de taal Java opkwam zag ik, en veel van mijn collega's, deze taal als C min min of C++ for dummies. Dat de taal Java een dergelijk grote invloed zou krijgen hadden we nooit gedacht maar inmiddels heb ik ook regelmatig code in Java geschreven, (ook voor Android) maar nooit van harte. Binnen de sector van besturingsystemen, compilers, systeemsoftware en vooral de game industrie is de taal C en "C++" niet weg te denken em is het nog steeds de meest gebruikte programmeertaal. Als het om snelheid en compacte code aankomt, kan er nog steeds geen enkele taal tippen aan de taal C. De beste 3D engines zijn dan ook allemaal in C of "C++" geschreven. Linux en Unix en zelfs Windows zijn voor het grootste gedeelte in C en "C++" geschreven. Soms noem ik de taal c wel eens de moeder van alle andere programmeertalen omdat de meeste compilers en tools voor andere programmeertalen en bijna altijd de runtime bibliotheken in de taal C geschreven zijn.

Ik geef ruiterlijk toe dat de taal niet eenvoudig is, erg cryptisch kan zijn, zeer veel vrijheden aan de programmeur geeft en (bijna) geen enkele runtime controle kent. De taal is zo krachtig dat u alles maar dan ook alles fout kunt doen, het vergt een goede kennis, netheid en discipline van de programmeur. Als resultaat van deze inspanning krijgt u de meest snelle en compacte code die mogelijk is. Ook geef ik toe dat een goed geschreven stuk broncode in de taal C soms net een kunstwerk is, maar dat is juist ook de enorme charme van deze taal. Wanneer ik de taal C vergelijk met muziek dan is het te vergelijken met Jazz, ook dit is een kunst op zich. Nog een goed vergelijk van de programmeertaal C is met een raceauto, het is compact gemaakt voor snelheid zonder toeters en bellen en niet voor comfort. Java is in dit vergelijk een degelijke gezinsauto met veiligheid voorop, ook niet slecht maar met een ander doel. Ik schrijf nog steeds in te taal C, mijn programma PragtFotoManager is in C en in Win32 geschreven wat resulteert in een zeer compact programma (230kb) dat supersnel is en erg veel functionaliteit kent. Het grappige is dat ik de programmeertaal C overal weer tegenkomt zoals in de programmeer omgeving voor de bekende Arduino minicomputer bordjes. Deze pagina gaat over mijn oude maar ook levenslange liefde voor de programmeertaal C, veel plezier met lezen en ik hoop ook u nog een beetje enthousiast te krijgen voor deze prachtige programmeertaal. Vriendelijke groet, Hein Pragt

Historie van de programmeertaal C

In 1978 ontwikkelden Brian W. Kernighan en Dennis M. Ritchie de programmeertaal C waarvan de wortels liggen in de 'B Computer Programming Language' (bcpl), een taal die in 1969 ontwikkeld werd. De C taal evolueerde uit bcpl via een verbeterde versie, die B genoemd werd. Al deze talen hebben de eigenschappen van een hogere programmeertaal: meerdere statements kunnen in blokken gegroepeerd worden, onder andere zijn er constructies voor conditionele uitvoering (if) en constructies voor herhaalde uitvoering (while). Bovendien kennen al deze talen het begrip pointer, staan het rekenen met pointers toe ('pointer arithmetic') en kennen het samenstellen van grote eenheden uit kleinere datatypen zoals structs, unions en arrays. Bij het ontwikkelen van de programmeertaal C hadden Kernighan en Ritchie een aantal duidelijke doelstellingen, in de eerste plaats moest C een snelle taal worden, geschikt voor een breed scala van toepassingen en zeker voor het schrijven van een besturingssysteem. De taal C is een zeer 'low level taal' en het is maar één stap hoger dan assembler en leent zich dus uitstekend voor programma's die zeer dicht bij de architectuur ('hardware') van de computer liggen zoals besturingssystemen en drivers.

In het unix besturingssysteem heeft C assembler zelfs bijna geheel verdreven, alleen een stukje van de kernel (bij het laden van het besturingssysteem zelf, de 'bootstrapping') is in assembler geschreven. Een tweede belangrijke overweging bij de opzet van de programmeertaal C is de splitsing van de C compiler en de C functiebibliotheek. De C compiler kan niets anders dan het omzetten van een brontekst naar machine instructies alle functies van de taal zijn opgenomen in een standaard C functiebibliotheek. Zo bevatten de meeste functiebibliotheken een aantal low level input/output functies, die dichtbij het besturingssysteem van de computer staan. Deze low level functies worden in een tussenlaag gebruikt door een 'high level' functie als printf() om bijvoorbeeld uitvoer te formatteren. De eerste versie van C, door B.W. Kernighan en D.M. Ritchie uit 1978 staat bekend als de standaard-C. Sinds deze versie is C zeer populair geworden, en al snel verschenen er verschillende C dialecten. In 1983 besloot het 'American National Standards Institute' (ansi) een commissie in te stellen die de C taal eenduidig en machine-onafhankelijk zou bepalen en het resultaat hiervan was de ANSI-C standaard. Tegenwoordig gebruikt men de programmeertaal C nog steeds voor het schrijven van computerspellen en programma's waar snelheid erg belangrijk is.

Online beginners cursus voor de programmeertaal C

Gewoon beginnen!

Als kennismaking met de programmeertaaltaal C wil ik beginnen met enkele heel eenvoudige programma's die de basis van elk C laten zien.

Eerste voorbeeld:

/* Mijn eerste C programma */

#include 

void main() 
{
  printf("Hallo wereld!\n");  // Druk het af
}

Na het compileren en uitvoeren van dit programma staat, als alles goed is gegaan, de tekst Hallo wereld! op het scherm. Ik zal nu dit programma regel voor regel uitleggen, het programma begint met een commentaarregel en het is een goede gewoonte om elk stuk broncode met een of meerder commentaarregels te beginnen. Commentaar is tekst die door de compiler genegeerd zal worden en alleen een extra aanwijzing of geheugensteuntje voor de programmeur is. Commentaar begin met de tekencombinatie /* en eindigt met de tekencombinatie */ waarbij deze begin en einde markeringen op dezelfde regel mogen staan maar ook over meerdere regels mogen lopen.

De regel #include <stdio.h> geeft aan dat een ander bestand in dit programmabestand tussengevoegd moet worden op deze plaats. In C maakt met vaak gebruik van zogenaamde include bestanden met het achtervoegsel .h waarin alle constanten en declaraties van functies van een ander stuk C broncode staan of de declaraties van een standaard bibliotheek. In dit geval gaat het om de bibliotheek stdio.h die definities bevat voor de standaard invoer en uitvoer (toetsenbord en scherm). Hier staat ondermeer de definitie van de functie printf() in die we zo gaan gebruiken. Op de volgende regel staat de functie main() uitgeschreven, dit is altijd de eerste functie die het gecompileerde programma zal uitvoeren. Een functie is te herkennen aan de 2 ronde haken achter de naam waar tussen we de parameters voor de functie kunnen plaatsen. In dit geval zijn het dus lege ronde haken omdat onze functie geen parameters heeft. Daarna zien we een open accolade teken {, dit is in de programmeertaal C de start van een blok programmeerinstructies die bij elkaar horen (een samengestelde opdracht) en dit blok zal afgesloten worden door een accolade sluiten }.

Daarna staat de standaard bibliotheek functie printf() waarmee we bijna alles kunnen afdrukken. Ook hier zien we de ronde haken weer en nu staat hier de parameter voor de functie tussen. In dit geval is het een eenvoudige tekst reeks (string) waarbij het backslash \ teken een bijzondere betekenis heeft. De tekencombinatie \n zal een "newline" teken (volgende regel teken) in de tekenreeks opnemen. Er zijn vele variaties met het backslash teken die voor andere zogenaamde "control characters" staan zoals de \r "cariage return" en \t voor het "tab"teken. Ieder zogenaamd statement in C moet verplicht afgesloten worden met een puntkomma. Aan het einde van de regel ziet u de tweede vorm van commentaar in C door middel van de tekencombinatie // waarbij de compiler alles tot het einde van de regel zal negeren en daarna staat de sluit accolade van de functie main(). Wanneer u dit voorbeeld begrijpt kent u de elementaire basis van de programmeertaal C.

Het gebruik van blanco regels, spaties, tabs en inspringen is in de programmeertaal C totaal vrijgelaten, u mag uw code zo schrijven als u het zelf wilt, het is wel handig om u een beetje aan de stijl te houden die de meeste programmeurs gebruiken (dit leert u vanzelf door veel naar code van anderen te kijken) maar er zijn ook onder C programmeurs enkel hardnekkige verschillen, bijvoorbeeld in het plaatsen van de accolades en het inspringen. Als extreem voorbeeld kan het vorige stukje programma ook op de volgende wijze geschreven worden met precies hetzelfde resultaat.

/* Mijn eerste C programma */#include void main(){printf("Hallo wereld!\n");}

of

/* Mijn eerste C programma */

#include 

void main() {
  printf("Hallo 
  wereld!\n");  // Druk het af
}

of

// Mijn eerste C programma 

#include 

void main() 
{

printf("Hallo ");

     printf("wereld!");     printf("\n");  // Druk het af
}

Zoals u hier ziet kunt u in C heel eenvoudig bijna onleesbare programmacode schrijven, dit is in mijn ogen echt slecht gedrag, broncode is niet bedoeld voor een computer maar voor een mens. U komt uzelf vanzelf tegen wanneer u een hardnekkige fout moet zoeken in slordig geprogrameerd stuk broncode.

Variabelen

Voor het (tijdelijk) opslaan van gegevens in een computerprogramma hebben we in bijna elke programmeertaal de beschikking over zogenaamde variabelen. Een variabele is eigenlijk niets anders dan de naam van een hokje in het geheugen van de computer waar we iets in kunnen opslaan en weer terug kunnen lezen. Dit kan een getal zijn, maar ook een reeks tekens (string) en zelfs een aanwijzer (pointer) die weer naar een andere geheugenplaats kan wijzen. De programmeertaal C is een zogenaamde typed taal waarbij we dus bij het declareren (bekendmaken) van een variabel ook aan moeten geven wel soort data we er in willen stoppen en hoeveel, bijvoorbeeld hoeveel tekens in het geval van een string. In C kennen we een aantal basis datatype die aangeven wat we er in kunnen opslaan, dit zijn: char, int, float, double en void. Het type char wordt gebruikt voor het bewaren van ASCII tekens, het integer type int wordt gebruikt voor het opslaan van gehele getallen (met een beperkte waarde) en de typen float en double kan men gebruiken voor reële getallen. De variabele void geeft de waarde NIETS aan en kan dus ook geen andere waarde bevatten. Daarnaast ken de taal C zogenaamde type modifiers waarmee het basis datatype veranderd kan worden. De programmeertaal C beschikt over vier modifiers : signed, unsigned, long en short. Een int of char zijn standaard signed en long en short geven aan hoeveel bits (en dus de minimale en maximale waarde van de variabele) we willen gebruiken.

Voorbeeld van mogelijke combinaties van datatypen en modifiers:

Typeaantal bitsgetalswaarde
char 8 -128 t/m 127
unsigned char 8 0 t/m 255
int 16 -32768 t/m 32767
unsigned int 16 0 t/m 65535
long 32 -2147483648 t/m 2147483647
float 32 3.4E-38 t/m 3.4E+38
double 64 1.7E-308 t/m 1.7E+308

*) Deze waarden zijn wat er volgens de standaard minimaal in moet kunnen passen, op veel 32 bit systemen zal een int 32 bits zijn en dus gelijk zijn aan een long.

Om het nog meer verwarrend te maken kennen verschillende C compilers ook nog hun eigen datatypes, en zijn er in de laatste C standaard ook weer een aantal bijgekomen, mede omdat we nu ook 64 bits computers kennen. Deze basistypes kunt u echter bij elke compiler gebruiken. Elke variabel zo groot mogelijk definiëren is mogelijk maar wel een verspilling van snelheid en geheugengebruik. Wanneer ik in een reversiprogramma een miljoen speelvelden wil opslaan om te doorzoeken maakt het veel uit of ik 8 bits waardes of 32 waardes gebruik voor de speelvelden. Wanneer het type variabele dit toestaat kun u er ook mee rekenen. Het declareren (bekendmaken) van een variabele gebeurt door het noemen van een datatype en een unieke naam die u zelf mag kiezen. U kunt een variabel bij het declareren ook gelijk een initiële waarde geven, wanneer u dit niet doet zal er in de meeste gevallen een willekeurige waarde in staan die op dat moment in deze geheugenlocatie stond. Hier volgen een aantal voorbeeld programma's die gebruik maken van variabelen.

// Voorbeeld van int variabelen

#include <stdio.h>

void main() 
{
int getal1;
int getal2 = 4;
int getal3 = 0;

   getal1 = 2;
   getal3 = getal2 + getal1; 
   printf("Uitkomst is: %d\n",getal3);
}

De uitvoer zal zijn: Uitkomst is: 6

Hier declareren we drie variabelen, de eerste is een int waarbij we alleen de naam reserveren, de tweede en de derde variabele geven we ook een initiële waarde. Daarna kennen we de getal waarde 2 toe aan de variabele getal1, (we stoppen het getal 2 in de geheugenplaats die aangewezen word door de naam getal1). De variabel getal3 had de waarde 0 maar in de volgende regel overschrijven we deze waarde met de uitkomst van het optellen van de waarden van de variabelen getal1 en getal2. Getal3 zal nu de waarde 6 bevatten. We gaven al aan dat we met de functie printf bijna alles kunnen afdrukken en in dit geval drukken we een tekst met de waarde van een variabele af. In de tekst van de (formatting) string geven we door middel van de tekencombinatie %d aan waar we de waarde van een int variabel opgenomen willen zien, daarna volgt de naam van de variabelen die op deze plaats afgedrukt moet worden. In het volgende voorbeeld gebruiken we meerdere type variabelen:

// Voorbeeld van verschillende variabelen

#include <stdio.h> 

void main() 
{
int getal1,getal2;  // Twee variabelen in 1 keer
char teken;
float breuk;

   getal1 = 9;
   getal2 = 2; 
   getal1 = getal1 / getal2;
   teken = 'A';
   breuk = 9.0 /  2.0;
   printf("Getal1 = %d\n",getal1);
   printf("Teken = %c\n",teken);
   printf("Breuk = %f\n",breuk);
}

De uitvoer zal zijn:
Getal1 = 4
Teken = A
Breuk = 4.5

Als eerste laat ik zien dat na een type meerdere variabelen gedeclareerd kunnen worden die gescheiden moeten zijn met een komma. Zoals u ziet kunt u met de printf functie ook andere datatypes afdrukken zoals %c voor characters en %f voor floats. Aangezien de variabel getal1 van het type integer is kan hier dus alleen maar een geheel getal in opgeslagen worden. Na de berekening zullen dus de cijfers na de komma wegvallen. Bij de float breuk ziet u dat de cijfers na de komma wel opgeslagen worden. Ik moet wel in de berekening achter de getallen .0 opnemen om de compiler duidelijk te maken dat het om float waarden gaat.

Arrays

Voordat we verder gaan met string moeten we eerst het array behandelen. Tot nu toe declareerden we enkelvoudige variabelen zoals getal1, getal2 en getal3. We kunnen ook een lijst van getallen declareren en door middel van een index een van de waarden uit de lijst schrijven of lezen. Een array geven we aan door middel van rechte haken [ ] na een variabele naam. Het getal tussen de haken geeft aan voor hoeveel waarden we willen reserveren.

// Voorbeeld van int array

#include <stdio.h>

void main() 
{
int getal[3];

   getal[0] = 4;
   getal[1] = 7;
   getal[2] = getal[0] + getal[1]; 
   printf("Uitkomst is: %d\n",getal[3]);
}

We declareren hier een array van drie integers en daarna kennen we aan de eerste index waarde van het array de waarde 4 toe en aan de tweede index binnen het array de waarde 7. Let op dat in C de index van een array van 0 tot de lengte min 1 loopt, dit kan verwarrend zijn maar de echte doorgewinterde C programmeur heeft dit in zijn systeem zitten. In dit voorbeeld is het array niet erg handig maar wanneer we loops (programmalussen) behandelen zal het nut van arrays snel duidelijk worden. Net als elke andere variabel kunnen we ook een array bij de declaratie van initiele waarden voorzien. De waarden worden dan tussen accolades en gescheiden door een comma achter de declaratie gezet.


/* dagen per maand */
int dagen[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

Een vorm van een array met toch een paar bijzonderheden is het character array. De C standaard kent geen datatype string (veel andere programmeertalen wel), voor C is een string een array van characters. Om het einde van een tekenreeks (string) aan te kunnen geven gebruikt C het zogenaamde NUL teken wat we in C weergeven met de \0 tekenreeks. Ondanks dat C geen datatype string kent, bestaat er wel een grote standaard bibliotheek met string functies waarmee u character arrays kunt doorzoeken, lengte kunt bepalen, zoek en vervang kunt uitvoeren enz.

// Voorbeeld van een character array

#include <stdio.h>

void main() 
{
char tekst[] = "test";

  printf("Index1 = %c\n",tekst[0]);
  printf("Tekst = %s\n",tekst);
}

De uitvoer zal zijn:
Index1 = t
Tekst = test

Zoals u ziet declareer ik hier een array zonder een lengte aan te geven, C zal hier genoeg plaatsen reserveren om de waarde waarmee ik initialiseer op te slaan. Aangezien het hier om een character array gaat zal er automatisch een NUL teken achter gezet worden waardoor er in het geheugen dus: t e s t NULL opgeslagen is en het array dus 5 lang is. Denk hier even rustig over na want dit is heel belangrijk.

Zoals ik al aangaf zijn er in de programmeertaal C een aantal tekencombinaties die een speciale betekenis hebben, binnen het type char kunnen daarbij de volgende tekens gebruikt worden:
'\n' = nieuwe regel
'\t' = tab
'\a' = belsignaal
'\b' = backspace
'\f' = formfeed
'\r' = carriage return
'\v' = vertikale tab
'\\' = backslash zelf
'\'' = enkel aanhalingsteken
'\"' = dubbel aanhalingsteken
'\0' = nulteken

Pointers

De meeste bekritiseerde mogelijkheid van de programmeertaal C is tevens de meest krachtige. Een pointer is een variabele die verwijst naar een andere variabel of geheugenlocatie. Iedere processor kent micro-instructies om rechtsreeks met het geheugen te werken en de pointer in de programmeertaal C zal één op één naar deze micro-instructie van de processor omgezet worden. Dit maakt de pointer super snel maar ook zeer gevaarlijk, want wanneer onze pointer wijst naar een stuk geheugen waar we niet mogen kopen (systeemgeheugen) of naar variabelen die we niet bedoeld hadden dan overschrijf deze instructie zonder enige vorm van waarschuwing of controle het geheugen op de locatie waar de pointer op dat moment naar wijst. U begrijpt dat wanneer u pointers gebruikt u dus heel goed moet weten wat u doet en zelf de beveiligingen moet inbouwen. Een pointer (aanwijzer) is niets meer dan een variabele waarin een geheugenadres is opgeslagen. Wanneer we dus een pointer naar het adres van een variabele laten verwijzen dan kunnen we ook de waarde op dit adres opvragen. Om het nog ingewikkelder te maken kunnen we zelfs pointers naar pointers definiëren, maar dit is wel zeer geavanceerd gebruik wat u bijvoorbeeld in de memory management functies van een besturingsysteem terug kunt vinden. Pointers kunnen we ook in een array zetten, waardoor er pointer arrays ontstaan. Een toepassing hiervoor is een alfabetische index op een grote hoeveelheid data waarbij een array van 26 pointers het begin van elke letter aanwijst zodat we snel naar een bepaalde positie kunnen springen. Twee tekens zijn belangrijk bij het gebruik van pointer, het * teken voor een pointer variabel geeft aan dat we de inhoud willen van het veld waar de pointer naar wijst en met het & teken krijgen we het geheugenadres van een gewone variabele om een pointer te vullen met dit adres. Het volgende voorbeeld geeft dit aan.

// Voorbeeld van pointers

#include <stdio.h>

void main()
{ 
int getal, *pointer;
  
  getal = 4;  
  pointer = &getal;   // adres van var
  printf("Getal heeft de waarde: %d\n",getal);
  printf("Getal via pointer gelezen: %d\n",*pointer);
  *pointer = 5;
  printf("Getal heeft de waarde: %d\n",getal);
  pointer = 5; // Dit kan maar is enorme fout
}

De uitvoer zal zijn:
Getal heeft de waarde: 4
Getal via pointer gelezen: 4
Getal heeft de waarde: 5

De laatste instructie (pointer = 5) is volkomen legaal in de taal C, de pointer wijst nu naar geheugenlocatie 5 in deze computer, waar dit ook mag zijn, het is waarschijnlijk niet legaal om hier naar toe te schrijven. Door hier nu een waarde aan toe te kennen overschijven we ergens in het geheugen iets met als waarschijnlijk gevolg dat nu of later ons programma of het besturingsteem zal crashen. Ook kan het besturingsysteem dit afvangen en een memory error genereren, de meest subtiele fout is dat we een van onze eigen variabelen overschrijven waardoor ineens een totaal andere waarde heeft dan we verwachten. Dit zijn de meest moeilijk op te vinden programmeerfouten. Voordat u pointers gaat gebruiken moet u pointers wel heel goed begrijpen.

Operatoren en expressies

Het is leuk om variabelen te hebben maar we zullen er ook iets mee moeten kunnen doen, bijvoorbeeld er meer rekenen. Hier komen zogenaamde operatoren om te hoek kijken. De programmeertaal C kent verschillende operatoren, een operator vertelt de compiler wat voor een rekenkundige of logische bewerking verricht moet worden. In C worden drie soorten operatoren onderscheiden: rekenkundige operatoren, relationele of logische operatoren en bitwise operatoren. Aangezien de taal C gemaakt is voor zeer luie programmeurs is er vaak een zeer korte en compacte notatie mogelijk. Dit maakt code echt niet sneller (de optimizer van de compiler zal toch een expressie helemaal optimaliseren) en we moeten er wel aan denken dat broncode voor de mens is. De programmeertaal C kent de volgende rekenkundige operatoren:

+ optellen
- aftrekken
* vermenigvuldigen
/ delen
% modulo
-- met 1 verlagen
++ met 1 verhogen

Er zijn een paar typische C constructies mogelijk met deze operatoren die ik in de volgende voorbeelden duidelijk zal maken. De operator gevolgd door een = geeft aan de bewerking op dezelfde variabel van toepassing is, dus a += 3; is eigenlijk a = a + 3;. Nog compacter en sneller is a++; om de variabele a één eenheid ter verhogen of a--; om de variabele met één eenheid te verlagen. Nog een belangrijk verschil is dat ++a; de waarde ook met één eenheid verhoogt, maar er is een verschil tussen a++; en ++a; en dat zit hem in de waarde van de variabel in een expressie. Bij a++ zal eerste de waarde van a teruggeven worden waarna de variabele a verhoogd zal worden en bij ++a; zal eerst de waarde verhoogd worden en dan de waarde teruggeven worden. Deze bewerkingen kunnen we ook op pointers toepassen waardoor we dus een soort van aanwijzer door het geheugen kunnen schuiven. Bewerkingen als opvragen en tegelijk verhogen zijn in C ook mogelijk en worden ook heel vaak gebruikt. Het is dus belangrijk om alle voorbeelden hieronder te begrijpen.

// Voorbeeld van rekenkundige operatoren

void main()
{
int x,y,z;
int ar[3] = ;
int *ptr;

  x = 12;
  y = 3;
  z = x / y;  // = 4 
  z *= 2;     // = 8
  z = x++;    // = 12
  z = x;      // = 13
  z = --x;    // = 12
  z += 10;    // = 22
  ptr = &ar;
  z = *ptr;   // = 1
  ptr++;      // verhoog pointer
  z = *ptr++; // = 5
  z = *ptr;   // = 8
}       

De tweede groep van operatoren zijn de relationele en logische operatoren. Relationeel geeft aan of een relatie tussen waarden, zoals kleiner of groter of gelijk waar of onwaar is. De set van relationele operatoren bestaat uit de volgende lijst:

> groter dan
>= groter of gelijk
< kleiner dan
<= kleiner of gelijk
== gelijk aan
!= ongelijk aan

Logische operatoren hebben betrekking op AND, OR en NOT en deze kunnen gebruikt worden om meerdere relationele operatoren te combineren in een complexe expressie. Dit zijn de logische operatoren:

&& en (AND)
|| of (OR)
! niet (NOT)

// Voorbeeld van relationele en logische operatoren

void main()
{
int x,y,z;

  x = 12;
  y = 12;
  z = 8;

  x == y;   // True
  x == z;   // False
  x != z;   // True
  x == 12;  // True
  x > z;    // True
  x <= z;   // False   
  x == 12 && y == 12; // True
  x == 12 || y == 8;' // True
}       

Compound statement

Naast enkele statements kent de taal C ook blokken met gebundeld statement die bij elkaar horen. In een taal als Pascal kennen we de Begin en End om een blok aan te geven, in de taal C doen we dit door middel van de accolade openen en de accolade sluiten. Op elke plek waar u een enkel statement kunt toepassen kunt u ook door middel van de accolades een compound statement gebruiken. Voor de duidelijkheid is het van belang de accoladen op een overzichtelijke manier te plaatsen. Hier komt een verschil tussen C programeurs aan het licht, sommigen zetten de begin acolade op een nieuwe regel, ik ben van het soort die de open accolade achter het conditionele statemente plaatst.

Het conditionele statement

De meeste programmeertalen kennen een conditioneel statement in de volgende vorm:

als (conditie is waar)   dan (compound) statement
anders (compound) statement

In C 

if (expressie)  statement
else statement 

In de expressie mogen we alle operatoren gebruiken waarbij de uitkomst 0 gelijk is aan true en de waarde ongelijk aan 0 voor false staat. If en else mogen ook genest (in elkaar verweven) gebruikt worden, dit kan echter soms moeilijk leesbare broncode opleveren waarbij men soms niet goed kan zien bij welke ik de else hoort. Dit is eenvoudig te ondervangen door goed inspringen en altijd accolades te gebruiken, ook bij enkelvoudige statements. Een meer cryptisch gebruik van het if en else statement is het gebruik van de ? operator. Deze probeer ik zoveel mogelijk te vermijden omdat ik deze vorm erg onleesbaar vindt en het voor de uiteindelijk gecompileerde code niet uitmaakt omdat de optimizer van de compiler er dezelfde code van zal maken als van de if else variant. De notatie is wel erg kort:

expressie 1 ? expressie 2 : expressie 3;

Wanneer expressie 1 waar is dan wordt expressie 2 uitgevoerd anders expressie 3.

// Voorbeeld van conditionele statements

#include <stdio.h>

void main()
{
int x,y,z;

// geef x,y en z willekeurige waarden

  if (x == y) 
    printf("x is gelijk aan y\n");
  else
    printf("x is ongelijk aan y\n");
 
  if (x == y && x == z) 
    printf("x is gelijk aan y en gelijk aan z\n");
  // else is optioneel!
 
  if (x == y) { 
    printf("x is gelijk aan y\n");
    if (x == z) {
      printf("en x is gelijk aan z\n");
    }
  }
  else {
    printf("x is ongelijk aan y\n");
  }
  
  x = 12;
  if (x - 12) { 
    printf("True\n");
  }
  x = 12;
  y = 12;
  if (x = y) { 
    printf("Dit niet\n");
  }
  else { 
    printf("Dit wel\n");
  } 
}       

De laatste variant is de meest gemaakte fout in de programeertaal C, het is een assignment, we maken de waarde x gelijk aan y en het resultaat is NIET 0 dus false. Hierdoor zal ALTIJD de else uitgevoerd worden tenzij y de waarde 0 heeft. Let op deze fout! Bij een hoog warning level zullen de meeste compilers hier wel een warning voor geven, ik compileer zelf altijd op het hoogste warning level en hanteer WARNING == ERROR.

Het meerkeuze statement (switch)

Met if en else kan een lange rij van condities worden opgesteld waardoor het programma snel onleesbaar kan worden. Soms willen we in één test meerdere waarden testen en bij elke waarde iets anders uitvoeren. Hier is een switch statement erg handig voor te gebruiken. Bij iedere case waarde hoort een (compound) statement en wanneer de compiler een break tegenkomt zal het doorvallen naar het einde van de switch. Wordt de break weggelaten dan zal het volgende statement ook worden uitgevoerd. Wanneer aan geen van de cases wordt voldaan zal het default statement worden uitgevoerd.

// Voorbeeld van conditionele statements

#include <stdio.h>

void main()
{
int x;

// geef x een willekeurige waarde

 switch(x) {
   case 1:  printf("De waarde 1\n");
            break;
   case 2:  printf("De waarde 2\n");
            break;
   case 3:
   case 4:  printf("De waarde 3 of 4\n");
            break;
   default: printf("Andere waarde!\n");
            break;
 } 
}       

Loops in C

De programmeertaal C kent drie soorten iteratieve statements (lussen): het while statement, het do while statement en het for statement. Alledrie zullen ze een statement of een code blok enige malen herhalen tot er aan een bepaalde conditie voldaan wordt. Het verschil tussen deze drie varianten zit in de test conditie en hoe vaak moet iets herhaald moet worden. Wanneer het een vooraf vast staand aantal keren betreft kan het beste gebruik worden gemaakt van een for statement, in andere gevallen is de while handiger. Een for loop in C ziet er nogal cryptisch uit. De formele syntax is:

for (initialisatie; conditie; increment) statement
De drie componenten zorgen voor een heel flexibel gebruik van het for statement, de initialisatie kent een begin waarde toe aan de zogenaamde loop control variabele (index), de conditie is een relationele expressie welke bepaald of de loop beëindigd moet worden, hier kan de loop control variabele maar ook elke andere variabel in gebruikt worden, en als laatste de stapwaarde bepaald hoe de loop control variabele wijzigt bij elke iteratie van de loop. Het krachtige van het for statement in C is dat de teller ook af kan lopen met elke zelfgekozen stap en dat de conditie van alles mag bevatten. Ook kunnen er meerdere loop index waarden tegelijk worden gebruikt met elk hun eigen stap. Het is niet noodzakelijk dat alle componenten van de for syntax aanwezig zijn. Elk onderdeel van de for loop is optioneel en zo kunnen er vreemde varianten ontstaan.

// Voorbeeld van for loops

#include <stdio.h>

void main()
{
int x,y;

  // druk 0..10 af
  for (x=0; x<10; x++) 
    printf("X = %d\n",x); 

  // druk 0 2 4 6 ..10 af  
  for (x=0; x<10; x += 2) 
    printf("X = %d\n",x); 
  
  // druk x 0 2 4 6 ..10 af
  // druk y 10..1 af
  for (x=0, y=10; x<10; x += 2, y--) {
    printf("X = %d\n",x); 
    printf("Y = %d\n",y); 
  }
}       

De tweede vorm van loop (lus) is de while loop en in C heeft deze de volgende syntax:

while (conditie) statement
Zolang de conditie waar is zal het statement of blok met statements worden uitgevoerd. Belangrijk is dat de test eerst uitgevoerd zal worden en wanneer deze gelijk onwaar is zal het statement dus nooit uitgevoerd worden. In het volgende voorbeeld gebruiken we ook even de functie getchar() uit de standaard library. Deze zal een ingedrukte toets teruggeven. Putchar is ook een functie uit de standaard library die een teken op het scherm afdrukt. Zie hier de meest eenvoudige tekstverwerker.

// Voorbeeld van while loop

#include <stdio.h>

void main() 
{ 
char ch = '\0'; 

  // stop als Q ingetikt is
  while (ch != 'Q') { 
    ch = getchar();
    putchar(ch);
  }  
}     

In tegenstelling tot de for en de while, test de do while loop de conditie aan het einde van de loop, de loop zal dus minimaal één keer uitgevoerd worden. Afgezien hiervan is de de do while constructie gelijk aan de while.

// Voorbeeld van while loop

#include <stdio.h>

void main() 
{ 
char ch; 

  // stop als Q ingetikt is
  do { 
    ch = getchar();
    putchar(ch);
  } while (ch != 'Q');
}     

Break, contnue en goto

Het break statement zijn we al eerder tegengekomen als de beëindiging van een case maar break kan ook als een beëindiging van een loop worden gebruikt. Indien meerdere loops genest zijn zal break alleen zorgen voor het stoppen van de loop waarin het voorkomt.

Door middel van het continue statement zal onmiddellijk naar de volgende stap van de loop gegaan worden en zo kan men binnen een loop een deel van de code overslaan. Dit kan efficiënt zijn omdat bijvoorbeeld na één test binnen de loop al duidelijk is dat de rest van de testen niet nodig is.

Dan komen we bij het meest verguisde statement in de taal C, het goto statement. Hiermee kan men vanuit een lus en zelfs vanuit geneste lussen naar buiten de lussen springen naar een label. Veel mensen denken dat ze netjes programmeren wanneer ze geen goto gebruiken, ik vind dit stom omdat het goto statement zeker nuttig kan zijn. Het is duidelijker om in een foutconditie snel uit geneste lussen te springen met een goto dan moeilijk te doen en te zorgen dat men uit alle lussen doorvalt. Maar hier verschillen de meningen van verschillende programmeurs, ik ben van mening dat duidelijke code voor strakke regeltjes gaat.

// Voorbeeld van break, continue en goto

#include <stdio.h>

void main() 
{ 
int i,y; 
  
  y = 20;
  for (i=0; i<10; i++) (
    y = x * 2;
    if (y > 10) 
      continue; 
    printf("Kleiner dan 10");
    // verlaat lus als y == 18
    if (y == 18)
      break;       
  }    

  for (i=0; i<10; i++) (
    for (y=0; y<10; y++) (
      printf("Waarde: %d\n",x * y);
      if (i ==5 && y == 8)
        goto marker;
    }
  }
marker:  
  
}     

Programmeren in C++

In dit deel probeer ik ook een aantal goede redenen te geven om over te stappen op 'C++' zonder het object georiënteerd deel te gebruiken. Dit is in mijn visie de eerste stap die 'C' programmeurs kunnen maken zonder een cultuur schok door te maken. Object georiënteerd programmeren is namelijk een andere denk en ontwerp wijze in plaats van alleen wat nieuwe functies. Maar 'C++' is heel goed te gebruiken zonder object georiënteerd te werken. Ik ontdekte ook dat zonder object georiënteerd programmeren de taal 'C++' een sterk verbeterde 'C' is, en ik zal proberen uit te leggen waarom.

Hele strikte type controle

De controle op variabele en functie types is heel strikt in 'C++', dit houdt in dat als U alles heel goed moet declareren. Als U een ander type parameter wilt gebruiken dan de gedeclareerde, of in een expressie verschillende data types gebruikt, bent U verplicht een cast te gebruiken. Dit geld ook voor signed en unsigned en char naar int conversie. Zo slordig als we in 'C' kunnen zijn kan in 'C++' absoluut niet. Dit lijkt wat omslachtig maar het zorgt ervoor dat we beter aangeven aan de compiler wat we eigelijk willen, en voorkomt veel programmeer fouten.

Ik vind het prettig om goed door een compiler op mijn vingers gekeken te worden, en compileer dan ook meestal op het hoogste warning niveau. Dit is gratis controle door de compiler, en dit heeft me al redelijk wat bugs bespaart. Helaas is het met Microsoft nog wel eens zo dat hun eigen include files niet zonder warning op het hoogste warning niveau gecompileerd kunnen worden. Dit los ik dan op door rond de #include file een #pragma te gebruiken om de warnings tijdelijk uit te zetten.


Verbeterd commentaar

'C++' heeft een verbeterde methode om commentaar te plaatsen. Naast de bestaande methode door middel van /* ... */ staat C++ het ook toe, door middel van een // dubbele slash de rest van de regel als commentaar te beschouwen. (Dit was in de meeste ANSI compilers ook al mogelijk.)


Andere cast methode

'C++' kent een verbeterde cast, in plaats van (long) var kan nu ook long(var) geschreven worden, wat een stuk duidelijker aangeeft wat we bedoelen.


result = long(var1) * var2;

TestFunc(long(IntVar),Str); 


Verplichte functie declaraties

In 'C++' moet elke functie gedeclareerd worden voor ze gebruikt word, dit verplicht de programmeur tot netjes declareren. Ook dit is weer extra controle door de compiler van de programmeur. Als deze de functie anders wil aanroepen, is hij verplicht een cast te gebruiken. (Dit was in ansi 'C' ook al aanbevolen maar niet verplicht.)


Functie overloading

Binnen 'C++' word behalve de functie naam ook de parameters en de return waarde gebruikt in de symbol table. Dit houdt in dat we dezelfde functie met andere parameters kunnen declareren zonder iedere keer een andere naam te bedenken. Denk hierbij aan de functies atoi() atof() atol() uit de standaard 'C' library, welke in 'C++' een functie kunnen zijn.

In 'C' zouden we het afdrukken van verschillende types zo oplossen:


void DrukafInt(int getal)
{
  // Code
}
void DrukafLong(long getal)
{
  // Code
}
void DrukafStr(char *str)
{
  // Code 
}

void TestFunc()
{
  DrukafInt(10);
  DrukafLong(423424L);
  DrukafStr("test");
}
In 'C++' zoekt de compiler de goede functie afhankelijk van de parameters.

void Drukaf(int getal)
{
  // Code
}
void Drukaf(long getal)
{
  // Code
}
void Drukaf(char *str)
{
  // Code
}

void TestFunc()
{
  Drukaf(10);
  Drukaf(423424L);
  Drukaf("test");
}

Dit houdt in dat we voor alle parameter types een functie naam kunnen gebruiken.


Default parameters

In 'C++' kunnen we een functie met een variabel aantal parameters aanroepen, als we gebruik maken van default parameters.


void TestFunc(char *Str, int i = 5)
{
  // Druk resultaat af!
  cout << Str << " " << i;   
}

// Dit drukt 10 af
TestFunc("Dit is met twee parameters",10);
TestFunc("Dit is // Dit drukt 5 af


Meer vrijheid in het declareren van variabelen

In 'C++' kunnen variabelen overal gedeclareerd worden, en hun scope is het block {} waarbinnen ze zich bevinden. In 'C' moeten declaraties vooraf gaan aan statements, in 'C++' mag daar waar een statement toegestaan is, ook een declaratie staan. Dit maakt het mogelijk om bijvoorbeeld binnen if code blokken locale variabelen te gebruiken.


int TestFunc()
{
int i;  
// Deze variabele is globaal voor de hele functie

  // code
  if (var1> 100) { 
    int y;
  } // Hier stopt de scope van y


Verbeterd FOR statement

In 'C++' kunnen we de loop variabele in het for statement declareren. De scope van deze variabele is het vorige {} code block, hoewel we misschien verwachten dat de scope de for loop zou zijn. In dit voorbeeld is de variabele ind na de for loop ook nog te gebruiken.

void TestFunc()
{
  for (int ind=0; ind < 10; ind++)
  {
    // code
  }
} 


Eenvoudigere struct, enum en union notatie

In 'C++' kunnen we als we een structure gedeclareerd hebben, variabelen van dit soort zonder het woord struct declareren. Dit kon in 'C' ook wel door middel van een typedef, maar is in 'C++' prettiger opgelost.


struct Stype ;

Stype StructVar;
Dit geld ook voor enum en union.

enum Boolean ;

Boolean Gereed = FALSE;


Echte constanten

In 'C++' maakt het keyword const een variabele een echte constante. De compiler zal ook een foutmelding geven als de programmeur de waarde probeert te veranderen.


const int Cvar = 100;

void Test(const int index)
{
  // Hier geeft de compiler een foutmelding
  index = 5;
}

void Test()
{
// Ook hier geeft de compiler een foutmelding
  Cvar = 10; 
} 

// Dit zou in 'C' een foutmelding geven.
int Varray[Cvar]; 

Nieuwe input en output methode

Een van de belangrijkste wijzigingen in 'C++' is de vervanging van de standaard I/O library stdio in iostream. Het gebruik van iostream is heel wat eenvoudiger dan stdio, al is het even wennen voor de doorgewinterde 'C' programmeur. Hier volgen enkele voorbeelden:


// Output Hello world met een newline
cout << "Hello world\n";
// Idem
cout << "Hello world" << endl;

int   VarInt = 4;
int   Var1,Var2;
float VarFloat = 3.14;
char *Str = "Hello";

cout << Str << VarInt << VarFloat << endl;   

// Resulteert in Hello43.14

cout << setw(6) << setfil('*') <<



// Leest 1 integer uit de input stream

cin >> Var1 >> Var2;    

// Leest 2 integers uit de input stream

In 'C' schrijven we vaak voor standaard I/O:


  while (var1 = getchar())
    putchar(var1);
Dit schrijven we in 'C++' als:

  while(cin >> var1)
    cout << var1; 


Nieuwe geheugen beheer methode

In 'C++' kunnen we nu in plaats van de zeer omslachtige en overloaded functies alloc() en free() waarbij we zelf de lengte van objecten moesten berekenen, nu ook new en delete gebruiken. Dit hebben ze duidelijk van de taal Pascal geleend, en werkt heel prettig en efficiënt.


void TestFunc()
{
int *IntPointer;

  IntPointer = new int;
  *IntPointer = 12;
  cout << *IntPointer;
  delete IntPointer;
} 


void TestFunc()
{
int *IntPointer;

  IntPointer = new int(100);
  IntPointer(10) = 12;
  cout << IntPointer(10);
  // Let op bij arrays altijd [] gebruiken
  delete [] IntPointer;     
} 
Dit is zeer gemakkelijk in vergelijking met de oude 'C' methode.


Call by reference

In 'C++' kunnen we nu met call by reference werken in plaats van pointers. Dit maakt de code in bepaalde gevallen, heel wat duidelijker.
In 'C' zouden we het volgende schrijven:


void Swap(int *Var1, int *Var2)
{
int Tmp = *Var1;

  *Var1 = *Var2; 
  *var2 = Tmp;
}

void TestFunc()
{
int V1, V2;

// Voorbeeld aanroep functie swap;
  Swap(& V1, & V2);
}

In 'C++' kunnen we dit op de volgende wijze doen:


void Swap(int& Var1, int& Var2)
{
int Tmp = Var1;

  Var1 = Var2;
  var2 = Tmp;
}

void TestFunc()
{
int V1, V2;

 // Voorbeeld aanroep functie Swap in C++
  Swap(V1,V2);    
}



Conclusie

Bij de meeste compilers is het omschakelen van 'C' naar 'C++' simpelweg het veranderen van de extensie van de source file van TEST.C in TEST.CPP waardoor de compiler weet dat de source file een 'C++' file is. Als U dit doet moet U dit voor alle files doen, omdat 'C' code geen 'C++' kan aanroepen. Omgekeerd is wel via een speciale declaratie mogelijk maar ik raad het af 'C' en 'C++' files door elkaar te gebruiken. Verder kan het aanroepen van zelfgeschreven library functies problemen gaan geven, omdat deze verwachten volgens de 'C' conventie aangeroepen te worden.

Omdat 'C' een subset is van 'C++' kan elk 'C' programma ook door een 'C++' compiler gecompileerd worden. Laat U niet afschrikken door het grote aantal warnings, en zet vooral het warning level niet lager om het aantal warnings terug te brengen. Besteed daarentegen eens een tijdje aan het plaatsen van casts en de kans is groot dat U terloops ook nog een programmeer fout ontdekt.

Tot mijn verbazing zijn er nog steeds bedrijven waar code uitgeleverd word, met een flink aantal compiler warnings, omdat de programmeur denkt dat hij weet wat hij doet, en hij vindt dat de compiler te kieskeurig is. In mijn visie is elke warning een mogelijke programmeer fout, en moet weggewerkt worden.

De basis van object georiënteerd programmeren.

Voordat ik begin uit te leggen wat object georiënteerd (vanaf nu OO) programmeren is, begin ik met een definitie wat objecten zijn. Objecten zijn alle dingen die wij kunnen bevatten, met duidelijk afgebakende grenzen. Voorbeelden zijn, een punt op het scherm, een pomp, een bankrekening, een computer, een mens of een programmeertaal. Twee verschillende objecten zijn duidelijk van elkaar te onderscheiden.

Een object heeft een aantal kenmerken:


De buitenwereld heeft geen directe toegang tot het saldo van de bankrekening, maar kan alleen via de boodschappen (member functies) de huidige toestand opvragen, of iets aan de huidige toestand te veranderen.

Een class is een definitie van een object, waarmee instances (echte objecten) van de class gemaakt kan worden. Een class op zich is geen object, er kunnen objecten mee gemaakt worden. Van een class kunnen we meer dan een object (instances) maken. De class is vergelijkbaar met een gietvorm waar we veel dezelfde beeldjes mee kunnen gieten.
In de class definiëren we een interface. We kunnen alleen met een object communiceren via deze interface. Ook definiëren we in de class de interne data, waarin we de toestand van een object opslaan. Interne data is dus ingekapseld en niet direct benaderbaar door de buitenwereld.
OO software is gebaseerd op deze objecten. Een object kunnen we beschouwen als een "gesloten apparaat" met een vast gedefinieerde interface. We hoeven niet te weten wat er zich in het object bevind, we kennen de interface waarmee we communiceren met het object.

Een voorbeeld is een televisie toestel.
We hoeven niet weten wat er in de T.V. zit, we gebruiken alleen de knoppen en het scherm als interface. Als we een andere zender willen kiezen, veranderen en we niet de afstemkring door binnen in het toestel aan een van de onderdelen te draaien, maar we geven de interface via een knop de opdracht op een andere zender af te stemmen. Via deze knoppen kunnen we ook zenders zoeken en in het geheugen van de T.V. opslaan. Hoe dit intern gebeurt willen we niet weten, en is voor het normaal gebruik van het toestel niet belangrijk. Intern kan dit in verschillende toestellen anders opgelost zijn, vanuit de interface zien we hetzelfde. Deze inkapseling van data en methodes is de basis van OO programmeren.

De interface functies zijn ook weer onder te verdelen in vier soorten:


De constructor en destructor zijn interne functies van het object, de modifier en de selector zijn van buiten het object te gebruiken.

Doordat de buitenwereld geen directe toegang heeft op de interne data van een object, kan via de interface functies bijvoorbeeld validatie plaatsvinden. Als gedefinieerd is dat een bankrekening niet negatief mag zijn kan de member functie VerlaagSaldo een controle uitvoeren of het saldo door deze bewerking niet negatief kan worden. In dit geval kan de member functie een fout afhandeling starten of een foutmelding genereren.
De interface bewaakt dus de interne toestand van een object.

De tegenhanger van OO programmeren is het procedure gericht programmeren. Hier staan de bewerkingen centraal, in tegenstelling van OO programmeren waar de gegevens en hun toestand centraal staan. In OO begint men met een data model, waarna men deze via objecten in categorieën onderbrengt, om daarna de interface en de bewerkingen te definiëren. Dit is duidelijk een andere aanpak, die het ook nodig maakt eerst over het programma en het data model na te denken. Dit in contrast met procedure gericht programmeren waar vaak een globale opzet van een programma word gemaakt, waarna deze procedures uitgewerkt worden. Dit is niet per definitie een slechtere aanpak, maar een andere, die ook zijn voordelen kan hebben.
Ik heb wel eens te horen gekregen, als is een ontwerp op papier aan het maken was, "wanneer begin je nu met het project". Deze mensen dachten dat het inkloppen van code het programmeren is. Dit is echter maar een klein deel van het programmeer werk. Het meeste is ook zonder computer te doen.

Een tweede eigenschap van OO programmeren is overerving.

Als we eenmaal een class gedefinieerd hebben, ligt deze vast. Als er nu een specialisatie plaats moet vinden, kan de reeds ontworpen class als basis dienen voor een nieuwe class. De nieuwe class bevat alle onderdelen van de oorspronkelijke class, met een aantal toevoegingen speciaal voor de nieuwe class. Als we een bankrekening zonder rente gedefinieerd hebben met een groot aantal bewerkingen, kunnen we hiervan een rekening met rente afleiden. De bewerkingen die we kunnen uitvoeren op de oorspronkelijke rekening kunnen we ook uitvoeren op de rekening met rente. Deze rekening heeft echter een paar uitbreidingen t.o.v. de oude rekening, en dat is een rentepercentage variabele, een functie om het rentepercentage op te vragen en een functie om het rentepercentage te veranderen. Ook zal er een functie moeten komen om de rente bij te boeken. De code om het saldo op te vragen en het saldo af te boeken hoeven we niet opnieuw te schrijven.

Dit is een eigenschap van OO programmeren die ik nogal eens uit de hand zie lopen. Een goede class hiërarchie opbouwen is een kunst, en soms zie je een ad-hoc class hiërarchie die ondoorzichtig en niet te onderhouden is.
Het werken met OO is geen garantie voor goede en goed onderhoudbare code. Een paar goede voorbeelden van een class hiërarchie zijn OWL van Inprise en MFC van Microsoft.

OO werken ten opzichte van procedureel programmeren betekend vaak de je veel vrijheden die je had moet opgeven en binnen een strakkere structuur moet werken. Dit voorkomt echter heel veel basis programmeer fouten, zodat het resultaat beter, en beter onderhoudbaar is.
Deze vorm van jezelf de beperkingen van een goede structuur opleggen, schrikt sommige 'C' en assembler programmeurs nog wel eens af. Een collega van mij plaagt me wel eens, als ik weer iets met de bestaande code wil doen waarin niet voorzien is, dat beperkingen opleggen geheel in de stijl van OO programmeren is. Ik probeer dan uit te leggen dat ik vanuit de bestaande code deze functionaliteit niet kan toevoegen, maar dat dit in een OO omgeving eenvoudig te doen zou zijn.

Het grote voordeel van OO programmeren is dat het uitnodigt tot goed gestructureerd werken, en dat je in staat bent goede interfaces te maken. Data hiding is in mijn visie een van de beste onderdelen van OO.


Gcc compiler onder Linux

© 2015 Hein Pragt

Op mijn Raspberry Pi programmeer ik in 'C' met gebruik van de gcc compiler. De gcc compiler is de "GNU" C Compiler en g++ is de "GNU C++ compiler". Hier staat een kleine uitleg met voorbeelden hoe deze compilers gebruikt kunnen worden. In voorbeeld 1 compileren we het bijna standaard programma "Hello world!", gebruik een editor onder linux vi is daar één optie, ik gebruik meestal de nano editor. Om de broncode te maken tikt u dan nano hello.c en voert u het volgende programma in:

#include "stdio.h"

int main() 
{
  printf("Hello world!\n");
} 

We kunnen dit programma vervolgens compileren met het volgende commando:

gcc hello.c -o hello 

Dit commando compileert en linkt hello.c naar een uitvoerbaar bestand met de naam "hello" dat uitgevoerd kan worden door hello of ./hello op de command line in te tikken. Het enige wat dit programma doet is de boodschap "Hello world!" op het scherm afdrukken, maar het is wel een teken dat de hele keten werkt. We kunnen ook de stappen van het compileren en linken uit elkaar trekken door middel van de volgende commando's, het resultaat zal hetzelfde zijn.

gcc -c hello.C
gcc hello.o -o hello 


NewbieIDE C en C++ IDE

© 2015 Hein Pragt

Ik was voor mijn dochtertje op zoek naar en eenvoudige maar wel krachtige IDE (compiler met editor in één) voor de programmeertaal c en ik vond het programma NewbieIDE. NewbieIDE is een gratis C ++ IDE waarmee je testprogramma's in C ++ kunt schrijven. Het is een eenvoudige en lichtgewicht applicatie ontworpen om beginners te helpen met een snelle start in C en C++. NewbieIDE is geschreven in VB.Net en gebouwd op de MinGW (Minimalist GNU for Windows) GCC compiler. Deze gratis C en C++ IDE is niet super krachtig maar het is echt effectief en snel in de uitvoering. Het wordt geleverd met een multi-interface met tabbladen die gebruikers in staat stelt om op een eenvoudige wijze een stuk sourcecode te schrijven en daarna met de F5 uit te voeren. NewbieIDE is open source software die gemakkelijk kan worden gedownload via de link aan het eind van dit artikel. De download zal als een ".7z" file komen, een gecomprimeerd bestandsformaat dat kan worden uitgepakt met behulp van gratis 7-Zip-compressie software. Daarna kunt u gewoon op de portable "NewbieIDE.exe" file uitvoeren om de IDE uit te voeren. NewbieIDE richt zich voornamelijk op C en C++ leerlingen en dus heeftr het een eenvoudige gebruikersinterface met alleen de noodzakelijke elementen. Dit omvat een menubalk, een werkbalk notering minimaal benodigde gereedschappen, een editor venster en een paneel voor het weergeven van het debuggen fouten. NewbieIDE ondersteunt de basisfuncties van een goede IDE inclusief regelnummering en syntax highlighting.
Download hier NewbieIDE


Visual Studio Express en community

© 2015 Hein Pragt

Zelf gebruik ik al meer dan 20 jaar de Microsoft C compilers, ik heb zeker 5 versie's op originele CD hier in mijn kast liggen en heb zelf nog een geldige licentie voor versie 4.2 en 5.0. Maar nu gebruik ik Visual Studio Community editie C++ wat een volledige versie is zonder beperkingen. Daarnaast kun u, wanneer u niet online wilt werken, de express edition 2010 en 2013 downloaden. Ik programmeer voor Windows zelf puur op win32, dat is dus standaard C met Win32 aanroepen om dingen op het scherm te zetten, systeemfuncties aan te roepen en de muis en het toetsenbord af te handelen. Het is een prima ontwikkel omgeving met ingebouwde debugger. In de nieuwste uitvoering kunt u er trouwens met bijna elke programmeertaal in werken.

Download Visual Studio Express C++

Visual Studio 2008 Express C++

Online boeken voor de programmeertaal C

© 2011 Hein Pragt

Hier staat twee pdf bestanden met een goede Nederlandstalige cursus voor de programmeertaal C. Alle aspecten van de taal komen in combinatie met goede voorbeelden aan de orde.

Een goede online cursus voor de programmeeraal C

Een goede online PDF cursus voor de programmeeraal C


Boeken over de programmeertaal C en C++

boek bestellen The C Programming Language - ANSI C Version Dit boek is nu redelijk duur maar mag niet in de boeknkast van elke ervaren C programmeur ontbreken. Dit boek is net als de programmeertaal C zelf, compact! Aan de hand van duidelijke voorbeelden worden de mogelijkheden van C steeds verder uitgelegd. Een absolute aanrader voor iedereen die C onder de knie wil krijgen, maar ook voor de gevorderde C programmeur een belangrijk naslagwerk. Er zijn genoeg kwalitatieve voorbeelden in te vinden en over elk onderwerp is genoeg informatie gegeven om het te kunnen begrijpen. Elke programmeur heeft zijn eigen programmeerstijl en ook in dit boek zie je dat terug.

boek bestellen Programmeren met C voor Dummies. C is een van de oudste en meest gebruikte programmeertalen. De invloed van C is zo groot dat verschillende andere talen (zoals C++, Java en JavaScript) grotendeels de syntaxis van C gebruiken. Programmeren met C voor Dummies is een toegankelijke introductie in het programmeren en de programmeertaal C. In heldere stap-voor-stapinstructies leer je de syntaxis van C kennen en ontdek je de logica achter het programmeren. Naast de basics komen ook geavanceerde aspecten van C, zoals pointers en gelinkte lijsten, aan bod. Met dit boek heeft C geen geheimen meer voor jou en ben je in no time klaar voor het leren van andere programmeertalen! Dan Gookin is de auteur van DOS voor Dummies, het allereerste Voor Dummies-boek. Hij wordt wereldwijd geprezen om zijn vele computing-bestsellers.

boek bestellen Leren programmeren, meten en sturen met de Arduino. De Arduino heeft elektronica en mechatronica toegankelijk gemaakt. Projecten die ooit veel kennis en ontwikkeling vergden, zijn nu in een handomdraai door iedereen te realiseren. Dit boek verschaft de benodigde basiskennis om uiteindelijk elke uitdaging op technisch gebied aan te kunnen gaan. Van procesautomatisering, telemetrie, human technology, mechatronica, smart technology en automotive tot en met smart grids, robotica en Internet of Things. Het boek stelt de lezer in staat om de basistheorie van deze vakgebieden op een praktische manier te leren kennen. Dit boek is bedoeld voor alle opleidingen, waarin toepassing en kennis van Arduino-microcontrollers relevant is. Door onder andere differentiatie in de oefeningen en grensoverstijgende opdrachten is het boek breed toepasbaar van VMBO-T tot en met het HBO.

Last update: 01-03-2020
Disclaimer: Hoewel de heer Pragt de informatie beschikbaar op deze site met grote zorg samenstelt, sluit hij alle aansprakelijkheid uit. Op de artikelen van de heer Pragt rust auteursrecht, overname van tekst en afbeeldingen is uitsluitend toegestaan na voorafgaande schriftelijke toestemming. Heinpragt.com is ingeschreven bij de KvK onder nummer: 73839426 en is gevestigd in Veenendaal.  Lees hier de privacyverklaring van deze site. Voor informatie over adverteren op deze site kunt u contact opnemen met: (mail@heinpragt.com).