To nie jest przekazywanie przez odniesienie, to jest przekazywanie przez wartość, jak twierdzili inni.
Język C jest przekazywany przez wartość bez wyjątku. Przekazywanie wskaźnika jako parametru nie oznacza przekazywania przez odniesienie.
Reguła jest następująca:
Funkcja nie może zmienić rzeczywistej wartości parametrów.
Spróbujmy zobaczyć różnice między parametrami skalarnymi i wskaźnikowymi funkcji.
Zmienne skalarne
Ten krótki program pokazuje wartość przekazywaną za pomocą zmiennej skalarnej. param
jest nazywany parametrem formalnym, a variable
przy wywołaniu funkcji nazywany jest parametrem faktycznym. Uwaga: zwiększenie param
funkcji nie zmienia się variable
.
#include <stdio.h>
void function(int param) {
printf("I've received value %d\n", param);
param++;
}
int main(void) {
int variable = 111;
function(variable);
printf("variable %d\m", variable);
return 0;
}
Wynik to
I've received value 111
variable=111
Złudzenie przejścia przez odniesienie
Nieznacznie zmieniamy fragment kodu. param
jest teraz wskaźnikiem.
#include <stdio.h>
void function2(int *param) {
printf("I've received value %d\n", *param);
(*param)++;
}
int main(void) {
int variable = 111;
function2(&variable);
printf("variable %d\n", variable);
return 0;
}
Wynik to
I've received value 111
variable=112
To sprawia, że uważasz, że parametr został przekazany przez referencję. Nie było. Został przekazany przez wartość, przy czym wartość parametru jest adresem. Zwiększono wartość typu int i jest to efekt uboczny, który każe nam myśleć, że było to wywołanie funkcji pass-by-reference.
Wskaźniki - przekazywane przez wartość
Jak możemy pokazać / udowodnić ten fakt? Cóż, może możemy wypróbować pierwszy przykład zmiennych skalarnych, ale zamiast skalara używamy adresów (wskaźników). Zobaczmy, czy to może pomóc.
#include <stdio.h>
void function2(int *param) {
printf("param's address %d\n", param);
param = NULL;
}
int main(void) {
int variable = 111;
int *ptr = &variable;
function2(ptr);
printf("ptr's address %d\n", ptr);
return 0;
}
W rezultacie oba adresy będą sobie równe (nie martw się o dokładną wartość).
Przykładowy wynik:
param's address -1846583468
ptr's address -1846583468
Moim zdaniem dowodzi to wyraźnie, że wskaźniki są przekazywane według wartości. W przeciwnym razie ptr
byłoby NULL
po wywołaniu funkcji.