So I was casually doing my usual theory proving code (testing things with code) and those code differences really got me thinking
#include <stdio.h>
int mutate(int a){
a =1;
printf("%d\n", a);
}
void main(){
int b = 1;
mutate(b);
printf("%d", b);
}
and
#include <stdio.h>
int mutate(int *a){
*a =1;
printf("%d\n", *a);
}
void main(){
int b = 1;
mutate(&b);
printf("%d", b);
}
Why in the first code there's a change without pointers in the first place.? Why there is a temporary change? The code with pointers I already understand though. Could someone explain though?
CodePudding user response:
You use two different ways to pass parameters.
The first implementation of the mutate
function uses call by value where a copy of the input parameter is created on the stack which is locally modified as you see in your print result. The value of the original input variable remains unmodified.
The second uses call by reference where a reference to the input variable is given and hence the input variable's value gets modified.
For a nice explanation see https://en.wikipedia.org/wiki/Evaluation_strategy, it also contains the following example which is extremely close to what you are doing:
void modify(int p, int* q, int* r) {
p = 27; // passed by value: only the local parameter is modified
*q = 27; // passed by value or reference, check call site to determine which
*r = 27; // passed by value or reference, check call site to determine which
}
int main() {
int a = 1;
int b = 1;
int x = 1;
int* c = &x;
modify(a, &b, c); // a is passed by value, b is passed by reference by creating a pointer (call by value),
// c is a pointer passed by value
// b and x are changed
return 0;
}
Now your example with output:
#include <stdio.h>
void mutate1(int a) {
a =1;
printf("value of a inside mutate1: %d\n", a);
}
void mutate2(int *a){
*a =1;
printf("value of *a inside mutate2: %d\n", *a);
}
int main(){
int b = 1;
printf("value of b before mutate1: %d\n", b);
mutate1(b);
printf("value of b after mutate1: %d\n\n", b);
b = 1;
printf("value of b before mutate2: %d\n", b);
mutate2(&b);
printf("value of b after mutate2: %d\n", b);
return 0;
}
$ gcc -Wall mutate.c
$ ./a.out
value of b before mutate1: 1
value of a inside mutate1: 2
value of b after mutate1: 1
value of b before mutate2: 1
value of *a inside mutate2: 2
value of b after mutate2: 2
$
As can be observed b
does not get modified when using call by value but it does when using call by reference.