Reputation: 31
So, I have an array containing 1 value. And then I copy(assign) it to another array. But, if I change the value on the second array, the value of first array got changed too. This is my code:
#include <stdio.h>
void change(int a[]){
int *temp = a;
for(int i=0; i<2; i++){
a[i] = temp[0]*10+7;
}
//What I expect for the result is a[0] = 7, a[1] = 7 instead of a[0] = 7, a[1] = 77
}
int main(){
int num[1];
num[0] = 0;
change(num);
printf("%d", num[0]);
return 0;
}
What happen to my array?
EDIT : I want to copy the value, not the address of array
EDIT 2: I have change a little bit of my code above to make it more clear what I want.
Upvotes: 0
Views: 3399
Reputation: 11152
First, this declaration
void change(int a[]);
is equivalent with this declaration
void change(int *a);
Second (see this link for more info),
The C language is pass-by-value without exception. Passing a pointer as a parameter does not mean pass-by-reference.
So you are passing a copy of the pointer's address (which points to the same array/address). Then you merely dereference the array's first position and assign a value to it (this really is just pointer arithmetic here).
Maybe it helps to rewrite the code in order to make the pointer arithmetic more obvious:
#include <stdio.h>
void change(int *a){
int temp[1];
*(temp+0) = *(a+0);
*(a+0) = *(temp+0) * 10 + 7;
}
int main(){
int num[1];
*(num+0) = 0;
change(num);
printf("%d", *(num+0));
return 0;
}
I am not sure how to understand the EDIT
EDIT : I want to copy the value, not the address of array
Looking at the code I fail to understand what you might want to try to achieve with this. Please clarify on this.
Having read your clarification I understand that you do not want to modify the array elements in the main
function yet modifying them in the change
function.
The answer is you cannot do that. The explanation is as mentioned above. I suggest you take some time to learn about pointer arithmetic and arrays in C. The K&R book is really excellent in that regard; I really recommend the book.
What you could do is copy the content of the array into another array and modify that one; e.g. in the beginning of the function or before calling the function and passing that copied array as parameter.
Upvotes: 0
Reputation: 21319
If you want to make a copy of an array inside a function so that you can work on the array copy without changing the original array, the best option is to make an explicit copy of the array yourself.
The most portable way to do this is by using malloc()
or calloc()
to allocate memory, and then copying the contents of the original array to the new memory allocation. If you choose this path your code must be sure to free any dynamically allocated memory when it is no longer needed. The copying can be done by looping and using array index notation to access the allocated memory, or by using memcopy()
to copy the contents of the original array. Another option is to use a Variable Length Array (added to C with C99, made optional in C11 and C17 but still widely supported) to avoid dynamically allocating and deallocating the memory yourself.
Here is an example program that contains two functions, work_on_copy()
and work_on_copy_vla()
, that each take an array, copy it, and do some work that changes the copy. A final argument provides an array index which is used to illustrate how the array copy can be used to modify the original array selectively after work has been done inside the function. If this argument is a valid array index, the value at that index is copied from the array copy to the original array.
Note that this problem could also be solved by wrapping an array in a struct
, but this method has the disadvantage of requiring that the array member of that struct
be the same size as the largest array that is expected, wasting memory in the general case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(size_t arr_sz, int arr[]);
void work_on_copy(size_t arr_sz, int arr[], int index);
void work_on_copy_vla(size_t arr_sz, int arr[], int index);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4 };
size_t my_arr_sz = sizeof my_arr / sizeof *my_arr;
puts("-- Do not change original array at all --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
putchar('\n');
puts("-- Change specified index of original array after work --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, 1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, 3);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
return 0;
}
void print_array(size_t arr_sz, int arr[])
{
for (size_t i = 0; i < arr_sz; i++) {
printf("%d ", arr[i]);
}
putchar('\n');
}
void work_on_copy(size_t arr_sz, int arr[], int index)
{
/* make copy of array: could return a pointer to this allocation */
int *arr_copy = malloc(sizeof *arr_copy * arr_sz);
/* handle error if allocation fails */
if (arr_copy == NULL) {
perror("unable to allocate memory");
return;
}
memcpy(arr_copy, arr, sizeof *arr_copy * arr_sz); // or use a loop
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] += 10;
}
printf("Array copy after work (malloc): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
/* deallocate memory to avoid memory leaks */
free(arr_copy);
}
void work_on_copy_vla(size_t arr_sz, int arr[arr_sz], int index)
{
/* make local copy of array using a VLA */
int arr_copy[arr_sz];
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] = arr[i];
}
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] *= 2;
}
printf("Array copy after work (VLA): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
}
Program output:
-- Do not change original array at all --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 2 3 4
Array copy after work (VLA): 2 4 6 8
Array in main(): 1 2 3 4
-- Change specified index of original array after work --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 12 3 4
Array copy after work (VLA): 2 24 6 8
Array in main(): 1 12 3 8
Upvotes: 0
Reputation: 19
If you want to pass a copy of an array to a function in C, you may put the array into a struct and pass this struct by value, e.g.
struct s {
int a[4];
};
void change(struct s elem)
{
elem.a[0] = 1; //assigment to copy
}
Upvotes: 0
Reputation: 114
"But, if I change the value on the second array, the value of first array got changed too"
Array is not passed as copy (arrays not passed by values) - it is a pointer pointing to an address where the first element is in memory. Therefore, you are actually modifying the values (arrays passed by reference)
Be aware ! When passing an array as a parameter :
void func(int a[])
means exactly the same as :
void func(int *a)
Upvotes: 4
Reputation: 653
When you use just an array's name to pass to a function, you actually create a temporary pointer to the first element of your array. So, your change() function receives as a copy of that temporary pointer the address of your num[] array in main.
The whole concept is called 'passing by reference'.
Upvotes: 0
Reputation: 18538
In c arrays are passed by reference. Meaning you are not passing the value but the adress where the elements of array are stored.
When you assign value to a[0] in a function, you are actually updating the num array.
Upvotes: 0