Linux C Programmeren Handleiding Deel 25 – Functie aanwijzers

Tot nu toe hebben we in deze doorlopende C programmeer-tutorial serie het basisconcept van wijzers besproken, en ook heel wat aspecten die met wijzers te maken hebben, zoals wijzers naar een array en array van wijzers. Uitbreidend op ons begrip van wijzers, bespreken we in deze tutorial het concept van wijzers naar functies.

Functie-aanwijzers in de programmeertaal C

Net zoals we wijzers naar variabelen hebben, kunnen er ook wijzers naar functies zijn. Hieronder volgt een voorbeeld van een functie-aanwijzingsdeclaratie:

void (*fn_ptr)(int)

Hier hebben we dus een functie-aanwijzer met de naam ‘fn_ptr’ die kan wijzen naar elke functie die leegte teruggeeft en een geheel getal als invoer accepteert. Onnodig te zeggen dat dit alleen nog maar het declaratiegedeelte is – net als elke andere pointer moet je hem een adres toekennen (dat van een functie in dit geval) om er gebruik van te maken.

Hieronder volgt een voorbeeld waarin van deze pointer gebruik gemaakt wordt:

#include <stdio.h>

void print_int(int a)
{
printf("\n The integer value is: %d\n",a);
}

int main()
{
void (*fn_ptr)(int);
fn_ptr = &print_int;
(*fn_ptr)(10);

return 0;
}

Zoals je ziet, definiĆ«ren we dus eerst een functie ‘print_int’ die een geheel getal aanneemt en leegte teruggeeft. Dan, in de ‘main’ functie, verklaarden we ‘fn_ptr’ als een functie-aanwijzer die kan wijzen naar functies als ‘print_int’. Daarna werd het adres van de ‘print_int’ functie aan ‘fn_ptr’ toegekend, en tenslotte werd de functie aangeroepen met behulp van de pointer.

Hier is de geproduceerde uitvoer:

The integer value is: 10 

Wat hier vermeldenswaard is, is dat je dit programma verder kunt vereenvoudigen door & en * uit de laatste twee regels te vermijden. Hieronder volgt de gewijzigde code:

#include <stdio.h>

void print_int(int a)
{
printf("\n The integer value is: %d\n",a);
}

int main()
{
void (*fn_ptr)(int);
fn_ptr = print_int;
fn_ptr(10);

return 0;

Verder gaand kun je, net als een array van aanwijzers, ook een array van functie-aanwijzers hebben. Hieronder volgt bijvoorbeeld een array van functie-aanwijzers waarin 3 functie-adressen kunnen worden opgeslagen.

void (*fn_ptr[3])(int)

En hieronder volgt een voorbeeld dat gebruik maakt van deze array van pointers:

void print_int1(int a)
{
printf("\n The integer value is: %d\n",a);
}

void print_int2(int a)
{
printf("\n The integer value is: %d\n",a+1);
}

void print_int3(int a)
{
printf("\n The integer value is: %d\n",a+2);
}

int main()
{
void (*fn_ptr[3])(int);

fn_ptr[0] = print_int1;
fn_ptr[1] = print_int2;
fn_ptr[2] = print_int3;

fn_ptr[0](10);
fn_ptr[1](10);
fn_ptr[2](10);

return 0;
}

Hier is de uitvoer die deze code oplevert:

The integer value is: 10 

The integer value is: 11

The integer value is: 12

Een ander aspect van functie-aanwijzers dat je moet kennen is dat je ze ook als functie-argumenten kunt gebruiken. Zo kan er bijvoorbeeld een functie zijn die een pointer naar een functie als argument accepteert. Bijvoorbeeld:

void some_random_func(void (*fn_ptr)(int)) 

Hieronder volgt een voorbeeldcode die deze functie gebruikt:

#include <stdio.h>

void another_random_func(int a)
{
printf("\n The integer to entered is: %d\n", a);
}

void some_random_func(void (*fn_ptr)(int))
{
fn_ptr(5);
}


int main()
{
some_random_func(another_random_func);
return 0;
}

Wat we hier dus deden is, we maakten een functie met de naam ‘some_random_func’ die een functie-aanwijzer in de invoer aanvaardt. Daarna riepen we vanuit ‘main’ ‘some_random_func’ aan met het adres van een andere functie ‘another_random_func’ als argument. Daarna riepen we met behulp van de pointer met succes ‘another_random_func’ aan.

Hier zie je de uitvoer:

The integer to entered is: 5 

Conclusie

Functie-aanwijzers kunnen van pas komen als je iets wilt maken dat een ‘callback mechanisme’ heet (lees er hier meer over). Maar voor je daaraan begint, is het beter als je dit concept goed begrijpt. We stellen voor dat je voorbeelden uit deze handleiding uitprobeert op je lokale machine (en ook nieuwe maakt). Laat bij twijfel of vragen hieronder een reactie achter.