Reputation: 361
I'm new to C and I have a doubt.
Since C functions create local copies of it's arguments, I'm wondering why the following code works as expected:
void function(int array[]){
array[0] = 4;
array[1] = 5;
array[2] = 6;
}
int main(){
int array[] = {1,2,3};
function(array);
printf("%d %d %d",array[0],array[1],array[2]);
return 0;
}
With the line output being 4 5 6.
Why does this work while the following doesn't?
void function(int integer){
integer = 2;
}
int main(){
int integer = 1;
function(integer);
printf("%d",integer);
return 0;
}
The output is just 1 in this case.
Short version: Why can functions modify the values of their parent variables if they are passed as array?
Thank you all!
Upvotes: 24
Views: 100673
Reputation: 24249
This is caused by the fact that arrays tend to decay into pointers.
int a[] = { 1, 2, 3 };
int* p = a; // valid: p is now the address of a[0]
a = p; // NOT valid.
printf("a = %p\n", a);
printf("p = %p\n", p); // prints same address as a
a
and p
will print the same value.
Contrary to what others have said, a
is not a pointer, it can simply decay to one. http://c-faq.com/aryptr/aryptrequiv.html
In your first function()
what gets passed is the address of the array's first element, and the function body dereferences that. Infact, the compiler is treating the function prototype as this:
void function(int* array /*you wrote int array[]*/){
array[0] = 4;
array[1] = 5;
array[2] = 6;
}
function(&array[0]);
This has to happen because you said "array of unknown size" (int array[]). The compiler could not guarantee to deduce the amount of stack required to pass by value, so it decays to a pointer.
---- Edit ----
Lets combine both your examples and use more distinctive names to make things clearer.
#include <stdio.h>
void func1(int dynArray[]) {
printf("func1: dynArray = %p, &dynArray[0] = %p, dynArray[0] = %d\n",
dynArray, &dynArray[0], dynArray[0]);
}
void func2(int* intPtr) {
printf("func2: intPtr = %p, &intPtr[0] = %p, intPtr[0] = %d\n",
intPtr, &intPtr[0], intPtr[0]);
}
void func3(int intVal) {
printf("func3: intVal = %d, &intValue = %p\n",
intVal, &intVal);
}
int main() {
int mainArray[3] = { 1, 2, 3 };
int mainInt = 10;
printf("mainArray = %p, &mainArray[0] = %p, mainArray[0] = %d\n",
mainArray, &mainArray, mainArray[0]);
func1(mainArray);
func2(mainArray);
printf("mainInt = %d, &mainInt = %p\n",
mainInt, &mainInt);
func3(mainInt);
return 0;
}
Live demo at ideone: http://ideone.com/P8C1f4
mainArray = 0xbf806ad4, &mainArray[0] = 0xbf806ad4, mainArray[0] = 1
func1: dynArray = 0xbf806ad4, &dynArray[0] = 0xbf806ad4, dynArray[0] = 1
func2: intPtr = 0xbf806ad4, &intPtr[0] = 0xbf806ad4, intPtr[0] = 1
mainInt = 10, &mainInt = 0xbf806acc
func3: intVal = 10, &intValue = 0xbf806ad0
In func1
and func2
"dynArray" and "intPtr" are local variables, but they are pointer variables into which they receive the address of "mainArray" from main.
This behavior is specific to arrays. If you were to put the array inside a struct, then you would be able to pass it by value.
Upvotes: 31
Reputation: 39
An array passed to a function is converted to a pointer. When you pass a pointer as argument to a function, you simply give the address of the variable in the memory. So when you modify the value of the cell of the array, you edit the value under the address given to the function.
When you pass a simple integer to a function, the integer is copied in the stack, when you modify the integer within the function, you modify the copy of the integer, not the original.
In C, we can use three types of memory :
In the case of this array passed by a function, which is a pointer (address to an other variable), it is stored in the stack, when we call the function, we copy the pointer in the stack.
In the case of the integer, it is also stored in the stack, when we call the function, we copy the integer.
If we want to modify the integer, we can pass the address of the integer to modify the value under the pointer, like this:
void function(int *integer)
{
*integer = 2;
}
int main()
{
int integer = 1;
function(&integer);
printf("%d", integer);
return 0;
}
Upvotes: 3
Reputation:
In the first code, you are passing the address of the array pointing to the top element in the array. So, when you modify the value in the function and return to the main function you are still accessing the same array which is in the same address. This is called pass by reference.
However, in the second case, the value of the integer is copied from the main function to the called function. In other words, the two integers are in different address in the memory. So modifying one does not modify the other.
Upvotes: 1
Reputation: 7290
The array name is a pointer to the first element in the array. In the first code sample you have passed a pointer to the memory location containing the first array element. In the second code sample you have passed an integer by value so it has nothing to do with the local variable named "integer"
check that link
Pass by reference and pass by value
Pass by Reference / Value in C++
Upvotes: 0
Reputation: 1944
There is a difference between 'pass by reference' and 'pass by value'
Pass by reference leads to a location in the memory where pass by value passes the value directly, an array variable is always an refference, so it points to a location in the memory. Integers will pass by value by default
Upvotes: 1