| D | E | L | P | H | I | R | O programmeren linux gitaar foto's email |
| sdl sql delphi componenten cpp c |
|
|
|
Pointers
Altijd een lastig onderwerp maar met de volgende weetjes kom je er wel uit;
Een voorbeeldStel je hebt de volgende -foutieve- code (uiteraard zonder regelnummers):
[01] #include <stdio.h>De argeloze programmeur zal aannemen dat de printf functie in regel [10] 12 en in regel [12] 24 zal weergeven, immers in regel [11] wordt i in de functie verdubbel met twee vermenigvuldigd! De werkelijke uitvoer blijkt echter 12 en 12 te zijn. Hoe kan dat? Dit heeft te maken met de 'scope' (geldigheid) van de variabele. Op het moment dat i in regel [08] aangemaakt wordt is deze lokaal in int main( void ) bekend.
Buiten main (dus bijvoorbeeld in void verdubbel( int x ) is deze
variabele niet bekend dus de functie kan er niks mee uithalen dat er voor zorgt dat
het resultaat bewaard blijft.In principe wordt er nu in de verdubbel functie een nieuwe variabele x aangemaakt (op een ander adres!); deze variabele x krijgt dezelfde waarde als i en wordt met 2 vermenigvuldigd en vervolgens wordt de functie afgesloten en is deze variabele niet meer bereikbaar. Er gebeurt dus helemaal niets met i! Hoe krijgen we het dan wel voor elkaar? Daar zijn pointers voor bedoeld. Een beter voorbeeldDe werkwijze is nu als volgt. We weten dat de functie verdubbel uit de vorige listing geen idee had van het adres van i. Dat adres moeten we dus meegeven, immers als deze functie het adres van i weet kan het ook de inhoud lezen en bewerken! We weten dat we met pointers het adres van een variabele kunnen achterhalen en hoeven nu dus nog alleen maar te weten hoe je dit in C programmeerd. Onthoud daarvoor de volgende syntax:
[01] #include <stdio.h>In deze code gebeurt het volgende; in regel [08] wordt gewoon een variabele aangemaakt (gedeclareerd) waarbij er dus in het geheugen een verwijzing naar een geheugenplek voor de inhoud van i gemaakt wordt. Het adres van deze plek kunnen we met &i achterhalen, de inhoud van i kunnen we met *i achterhalen. In regel [09] wordt de inhoud op 12 gezet. In regel [11] geven we het adres van i mee aan de functie verdubbel. De functie verdubbel kan met behulp van dit adres de inhoud van i ophalen en deze met behulp van regel [04] verdubbelen. In regel [04] staat eigenlijk; vermenigvuldig de inhoud van het adres wat we gekregen hebben met 2. Nu is de inhoud van i 24 geworden en zal dit getal ook door regel [12] weergegeven worden. Pointers naar structuresHet verhaal wordt wat lastiger met structures. Een structure bevat velden en deze worden bij pointers anders benadert dan normaal. Ook hier moet je twee belangrijke dingen weten;
[01] #include <stdio.h>Het principe van het programma moet na het lezen van het eerste stuk over pointers duidelijk zijn. Het nieuwe vind je in regels [17] en [18] waar de normale manier met de punt gebruikt wordt om waarden aan de velden x en y van P1 toe te kennen. In de functie die de pointer naar P1 heeft worden de waarden benaderd met ->. Het gebruik van een punt zou in dit geval tot de melding '
request for member `x' in `Punt', which is of non-aggregate type `coord2D *'
leiden.
Pointers naar functiesEen belangrijk onderwerp bij pointers zijn de pointers naar functies. Dit gebruik is niet echt eenvoudig maar biedt hele leuke mogelijkheden. Je kunt op deze manier een event (gebeurtenis) op meerdere manier laten afhandelen afhankelijk van bepaalde omstandigheden. Dit klinkt theoretisch en vraagt om een voorbeeld. Het volgende programma vraagt om één parameter 'w' of 'windows' of 'l', 'linux' (zonder haakjes) en geeft aan de hand van de gegeven parameter een bepaald welkomstbericht.
[01] #include <stdio.h>In regel [03] wordt een algemeen type gemaakt zoals de functie er uit komt te zien. We willen een functie die geen parameters teruggeeft en die ook geen parameters verlangt dus void (EenFunctie)( void ).In de regels [04] t/m [06] worden de drie functies alvast gedeclareerd (voorwaartse declaratie). Regel [08] geeft aan dat we geinteresseerd zijn in het aantal (argc) argumenten dat meegegeven wordt aan het programma. De argumenten komen in de array van pointers (voila.. daar is de pointer weer ;-) die in argv opgeslagen zijn. In regel [09] wordt een pointer naar een functie van het type EenFunctie aangemaakt. In regel [10] geven we alvast aan dat de normale functie die uitgevoerd moet worden de functie 'welkom_standaard' is. We doen dit hier door aan de pointer 'DeFunctie' het adres (&) van de functie 'welkom_standaard' te geven! In regels [12] en [13] wordt na wat controle (zijn er genoeg argumenten en begint het argument met een 'l' of een 'w') eventueel een andere functie aan 'DeFunctie' gehangen. In regel [15] wordt de functie daadwerkelijk uitgevoerd. Er was keuze uit drie functies en afhankelijk van de invoer wordt er één uitgevoerd omdat de pointer 'DeFunctie' naar één van de adressen van 'welkom_standaard' of 'welkom_linux' of 'welkom_windows' wijst. In de regels [19] tot en met [21] worden de functies die vooraf gedeclareerd zijn helemaal uitgeschreven. |
C code geschikt voor C++ maken
Je kunt in C er alvast rekening mee houden dat je functies ook in een C++ programma
gebruikt kunnen worden door de volgende code in je header file toe te
voegen; |
Welke library voor welke functie?
Stel ik heb het volgende programma (test.c) geschreven; 1 - compileer het programmadelphiro@laptop:delphiro gcc -c test.cJe hebt nu de beschikking over de object file (test.o). Deze stap gaat wel goed omdat je code nu nog niet gelinkt wordt. 2 - bekijk de afhankelijkhedenKijk met het volgende commando (inclusief spaties rond de U !) naar de objecten die het programma nodig heeft;delphiro@laptop:delphiro nm test.o | grep ' U 'De uitvoer is in mijn geval: U pow
Alle bestanden die met een U (undefined) worden voorafgegaan moeten aan een library gekoppeld worden. Deze kun je opzoeken met 'ar' of 'nm'. 3 - zoek de juiste libraryDe standaard locatie van de libraries is /usr/lib maar er zijn er waarschijnlijk nog meer geplaatst in /usr/local/lib en wellicht nog op andere locaties. De eerste plek om te zoeken is echter /usr/lib. In ons voorbeeld is pow dus niet gekoppeld en zoeken we de bijbehorende library;delphiro@laptop:delphiro cd /usr/libwaarbij de librarynaam één van de vele namen in de directory kan zijn. Uitleg; nm geeft alle symbolen weer die in een object bestand zitten. Vervolgens wordt door 'grep' gezocht naar een string in de vorm van 'pow in'. De substring 'pow' spreekt voor zich, het stukje ' in' is geplaatst om allemaal onzinmeldingen te voorkomen; zodra ergens de tekst 'pow in blabla.o' staat weten we dat dit de juiste bibliotheek is. Nu hebben we nog het probleem dat er HEEL veel libraries zijn. Hiervoor heb ik een (simpel) script geschreven dat ALLE libraries onder /usr/lib doorzoekt;
#!/bin/bashAls je dit script met de juiste invoer (ZOEKDIR en ZOEKTERM) uitvoert verschijnen er meldingen in beeld zodra de term is gevonden. Bij mij verschijnt er bv.
...
4 - Bouw het programma nogmaals maar nu goed!De functie is dus uitgewerkt in libgcj.a en libm.a. We kunnen deze nu toevoegen door de naam na lib bij het compileren als volgt toe te voegen.delphiro@laptop:delphiro gcc -o eenTest test.c -lmof delphiro@laptop:delphiro gcc -o eenTest test.c -lgjcIn beide gevallen wordt het programma goed gebouwd. NB Bij mij werkt dit allemaal prima.. maar ik draag uiteraard geen verantwoordelijkheid als dit bij anderen foutloopt. Ik heb het ook maar uitgezocht :-) |