Linux C Programmeren Handleiding Deel 8 – Call by Value Vs Call by Pointer/Address

In onseerste deel van deze doorlopende leerreeks bespraken we kort de functies, waaronder hun declaratie en lichaam. Wat we toen niet bespraken waren de vele manieren waarop functies aangeroepen worden. Hier, in deze zelfstudie, bespreken we snel de manieren die er zijn.

In de C taal kun je een functie op een paar manieren aanroepen: aanroepen door waarde en aanroepen door pointer of adres. Laten we deze beide begrippen bespreken met enkele gemakkelijk te begrijpen voorbeelden.

Stel dat je een programma wilt schrijven dat twee waarden verwisselt. Hier zie je hoe je dat kunt doen:

#include <stdio.h>

int main()
{
int a=0, b=0, c=0;

printf("Enter two integer values\n");

scanf("%d %d",&a,&b);

printf("Entered values are: %d and %d", a,b);

c = a;
a = b;
b = c;

printf("\nSwapped values are: %d and %d", a,b);



return 0;
}

Hier is de uitvoer van deze code met ingevoerde waarden als 5 en 9:

Enter two integer values
5 9

Entered values are: 5 and 9
Swapped values are: 9 and 5

Stel nu dat de eis is dat er een aparte functie komt – zeg ‘swap’ – die al het verwissel-gerelateerde werk doet en aangeroepen kan worden telkens als de programmeur twee waarden wil verwisselen. Hieronder volgt de code die dit doet:

#include <stdio.h>

void swap (int val1, int val2)
{
int temp = 0;

temp = val1;
val1 = val2;
val2 = temp;

printf("\nSwapped values are: %d and %d", val1,val2);

}

int main()
{
int a=0, b=0;

printf("Enter two integer values\n");

scanf("%d %d",&a,&b);

printf("Entered values are: %d and %d", a,b);

swap(a,b);

return 0;
}

Zo zie je maar. Er is een aparte functie met de naam ‘swap’ gemaakt die twee waarden (oorspronkelijk door de gebruiker ingevoerd en in ‘main’ functie opgevangen) als argumenten ontvangt en ze dan verwisselt en de uitvoer afdrukt.

De manier waarop ‘swap’ hier is aangeroepen staat bekend als ‘call by value’. De reden is dat bij de aanroep alleen de waarden die door ‘a’ en ‘b’ worden vastgehouden als argumenten aan de ‘swap’ functie worden doorgegeven. Deze waarden worden ontvangen door de argumenten ‘val1’ en ‘val2’, en het zijn deze variabelen waarop het ruilproces wordt uitgevoerd.

Dit betekent dat de variabelen ‘a’ en ‘b’ in de ‘hoofd’ functie de oorspronkelijke waarden blijven houden, ook nadat de verwisselbewerking is uitgevoerd. Maar wat als de eis is dat de waarden van ‘a’ en ‘b’ verwisseld worden na het aanroepen van de ‘swap’ functie? Welnu, hier komt de ‘call by pointer/address’ methode in beeld.

Wat we hier dus eigenlijk doen is, dat we het adres van variabelen (zoals ‘a’ en ‘b’ in ons geval) als argumenten doorgeven. De functie die aangeroepen wordt (‘swap’ in dit geval) is toegerust om adressen als argumenten te ontvangen en dan wordt het ruilproces uitgevoerd op de waarden die op deze adressen bewaard worden, wat effectief betekent dat de waarden van de oorspronkelijke variabelen (‘a’ en ‘b’ hier) verwisseld worden.

Nu, in de vorige paragraaf zeiden we dat de functie“is toegerust om adressen als argumenten te ontvangen”. Welnu, met “toegerust” bedoelden we dat de functie speciaal soort argumenten heeft die adressen kunnen ontvangen. Deze argumenten zijn variabelen van het type ‘pointer’. We zullen ‘pointers’ in een volgende tutorial uitvoerig bespreken, maar bedenk voor nu gewoon dat pointer variabelen geheugenadressen als waarden opslaan.

Hier zie je hoe een pointer naar een geheel getal gedeclareerd/definieerd wordt:

int *x;

Dus eigenlijk is x een aanwijsvariabele die gebruikt kan worden om geheugenadres van een gehele variabele op te slaan. Stel dat ‘i’ een geheel getal variabele is, dan kun je zo ‘x’ het adres van ‘i’ laten opslaan:

x = &i;

En telkens als je via ‘x’ toegang wilt krijgen tot de waarde van ‘i’, schrijf je ‘*x’. Zo kun je bijvoorbeeld de waarde van ‘i’ veranderen in, zeg, 10:

*x = 10;

Dus met dit alles in gedachten, zie je hier hoe je ‘swap’ kunt aanroepen met de methode call by address or pointer:

#include <stdio.h>

void swap (int *val1, int *val2)
{
int temp = 0;

temp = *val1;
*val1 = *val2;
*val2 = temp;

}

int main()
{
int a=0, b=0, c=0;

printf("Enter two integer values\n");

scanf("%d %d",&a,&b);

printf("Entered values are: %d and %d", a,b);

swap(&a,&b);

printf("\nSwapped values are: %d and %d", a,b);


return 0;
}

In plaats van de waarden van ‘a’ en ‘b’ als argumenten door te geven, hebben we deze keer dus de adressen van deze variabelen doorgegeven. In de functie ‘swap’ worden de adressen ontvangen in twee pointer variabelen (‘val1’ en ‘val2’). En met behulp van de twee pointer variabelen verwisselt de logica direct de waarden van ‘a’ en ‘b’.

Hier zie je de uitvoer:

Enter two integer values 
6 8
Entered values are: 6 and 8
Swapped values are: 8 and 6

Conclusie

Dit artikel zou je op z’n minst een basisidee moeten hebben gegeven van wat ‘call by value’ en ‘call by address/pointer’ manieren van functie-aanroepen zijn, en wanneer ze gebruikt kunnen worden. Probeer de voorbeelden uit die we hier opgesomd hebben en laat het ons in commentaar hieronder weten als je twijfels of vragen hebt.