I\'m trying understand how to pass a parameter by reference in C language. So I wrote this code to test the behavior of parameters passing:
#include
The answer posted by nos is correct.
Also note that the first of the two posted programs will actually crash on many systems, when the printf line in main() tries to dereference main's pointer n
, which was never set:
printf("%d.\n", *n);
Actually not really much a difference, except the first one is broken. :) (Well, both are, but the first is broken more).
Let me explain what happens in the second case:
n
of type pointer-to-int
is allocated on the stackint
is allocated to the stack, it's address is stored in variable n
alocar
is called, being passed the copy of variable n
, which is the copy of the address of our variable of type int
int
variable being pointed by n
to 12n
(12)The first case:
n
of type pointer-to-int
is allocated on the stackalocar
is called with a copy of the variable n
(which is still uninitialized - contains an unknown value)int
is created in memory and the local copy of variable n
in function alocar
is set to point to that new variablen
) is set to 12 and printedn
variable in main is still uninitialized, it points to a random place in memory. So the value in random place in memory is printed (which is likely to crash your program).Also, both programs are broken because they don't free the memory allocated by malloc().
You want to modify the value of n
in main
, not what n
points to, so you need to pass a pointer to it. Since the type of n
in main
is int *
, the parameter to alocar
needs to be of type int **
:
void alocar(int **n)
{
*n = malloc(sizeof **n); // note no cast, operand of sizeof
if (!*n)
exit(-1);
**n = 12;
printf("%d\n", **n);
}
int main(void)
{
int *n;
alocar(&n);
printf("%d\n", *n); // we've already tested against n being NULL in alocar
free(n); // always clean up after yourself
return 0;
}
See, what's happened in first program.
Before call to alocar we have just variable n in main, pointing to some undefined place:
main()::n [ X--]--->(?)
(there's value in square brackets, which is undefined, marked as X). Then we call alocar, and we have another variable in alocar's scope, which have a copy of origianl var.
main()::n [ X--]--->(?)
alocar()::n [ X--]-----^
Now, allocate some memory:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ Y ]
Assign value to allocated var:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ 12 ]
Return. alocar()::n is removed as it live only while alocar() is executed.
main()::n [ X--]--->(?)
[ 12 ]
main()::n is still pointing to some undefined place... (Which possibly stores value 0) And no one points to allocated place.
C is pass-by-value, it doesn't provide pass-by-reference. In your case, the pointer (not what it points to) is copied to the function paramer (the pointer is passed by value - the value of a pointer is an address)
void alocar(int* n){
//n is just a local variable here.
n = (int*) malloc( sizeof(int));
//assigning to n just assigns to the local
//n variable, the caller is not affected.
You'd want something like:
int *alocar(void){
int *n = malloc( sizeof(int));
if( n == NULL )
exit(-1);
*n = 12;
printf("%d.\n", *n);
return n;
}
int main()
{
int* n;
n = alocar();
printf("%d.\n", *n);
return 0;
}
Or:
void alocar(int** n){
*n = malloc( sizeof(int));
if( *n == NULL )
exit(-1);
**n = 12;
printf("%d.\n", **n);
}
int main()
{
int* n;
alocar( &n );
printf("%d.\n", *n);
return 0;
}