Changing array inside function in C
Your array in main is an array. It will decay to a pointer, to produce the behavior you expect, but it is not a pointer.
int a[10];
int* p = a; // equivalent to &a[0]; create a pointer to the first element
a = p; // illegal, a is NOT a pointer.
What your code is doing is copying the address of a into a function-local variable. Modifying it will have no more difference outside than changing length.
void change(int* local_ptr, size_t length)
{
local_ptr = 0;
length = 0;
}
int main()
{
int a[10];
int length = 10;
printf("before a=%p, length=%d\n", a, length);
change(a, length); // we copied 'a' into 'local_ptr'.
printf("after a=%p, length=%d\n", a, length);
}
If you wish to modify a pointer from the caller, you will need to use pointer-to-pointer syntax:
void change(int** ptr, size_t length)
{
// change the first element:
**ptr = 0;
// change the pointer:
*ptr = 0;
// but ptr itself is a function-local variable
ptr = 0; // local effect
}
However: There is a problem with what you are trying to do that goes deeper than this.
In your code, "int a" is an array on the stack, not an allocated pointer; you cannot free it and you should avoid mixing heap/stack pointers this way because eventually you'll free the wrong thing.
A simple example:
#include <stdio.h>
void print_array(const int arr[], const int n){
int i;
for(i=0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
void change_array(int arr[]){
arr[0] = 239;
arr[1] = 234234;
}
int main(){
int arr[10] = {};
print_array(arr,10);
change_array(arr);
print_array(arr,10);
return 0;
}
The output:
0 0 0 0 0 0 0 0 0 0
239 234234 0 0 0 0 0 0 0 0
Ok, i will make the answer short.
- Arrays are always passed by reference in C
change(array, length); In this line, it means reference to the first element of the array variable is passed to the function.
Now the function needs a pointer to catch the reference, it can be a pointer or it can be an array. Note that the pointer or the array is local to the function.
You received it in a pointer named array. Which is definitely a pointer but it is not the same as array in main function. It is local to the change function.
You declared a new array dynamically, and assigned a pointer named new with it. And all the changes you did were to new pointer.
Everything is ok till now.
- Now you assigned the new pointer to the array pointer which is local to the change function.
This is the real issue. As even though the array is in heap section, and it will remain in the memory, but the *array and *new are local pointer variables.
Also array pointer in change function is different from array pointer in main function.
The solution to this problem is Manipulate the data of array pointer directly.
void change(int *array,int length) { int i; for(i = 0 ; i < length ; i++) array[i] = 1; }
In this way you are directly overwriting values of array in main function. Everything else is correct.
Summerization: array pointer in change function is local to change function. array in main function is local to main function. Making change function's local array pointer point to array in heap section won't change data in actual array. You changed pointer's position, Not the array's data.
In c you can't pass a variable by reference, the array
variable that you assign inside the function contains initially the same address as the passed pointer, but it's a copy of it so modifying it will not alter the passed pointer.
You need to pass the address of the pointer in order to be able to alter it, like this
// Change the pointer of the array
void change(int **array, int length)
{
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
Then in main()
you cannot assign to an array, doing so through this kind of function is surely undefined behavior. The array defined in main()
is allocated on the stack and you cannot assign anything to an array since they are non-writeable lvalues so you cannot make it point to a heap memory location obtained with malloc()
, you need to pass a pointer like this
int *array;
change(&array, length);
free(array);
If you want the function to replace the previous array, it will have to free()
the malloc()
ed data (note that passing NULL
to free()
is well defined), so
// Change the pointer of the array
void change(int **array, int length)
{
free(*array);
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
then in main()
int *array;
array = NULL;
change(&array, length);
change(&array, length);
change(&array, length);
change(&array, length);
free(array);
will do what you apparently want.