问题
What if I want to make a function that takes in an array and modifies it.
void mod_Arr(int* arr) {
int*arr = int[3][3]; //arr is now an array
int*arrCpy = arr;
//some modification to arrCpy
}
``
1) will arr be modified as well? i.e must I include the line: arr = arrCpy; or should I instead use: arr = mod_Arr(arr) //and get mod_Arr to return an array? 2) Must I free(arr) to prevent old values of arr taking up space? In the case that the pointer now points to a new memory instead of modifying the values at the old address, must I clean up the useless stuff still in the old address?
回答1:
If you have an array in main() that is int a[3][3]; and you want to pass that array to your function such that it can be modified within the function and the changes seen back in the calling function (main() here), the you must pass the address of the array as the parameter. If you simply pass the array itself by-value, then the function receives a copy-of the array and any changes made to the array in the function are lost when the function returns -- just like any other locally declared array would be.
When you take the address-of an array, you have a pointer to the array. In your case a pointer to a 2D array. The syntax for the type above would be int (*a)[3][3]. (e.g. a pointer-to-array of int[3][3]) So to pass the address-of the array (it is still passing the address by-value, C does not have references), your function declaration would look like:
void mod_arr (int (*a)[ROWS][COLS])
{
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
(*a)[i][j] = (i + 1) * (j + 1);
}
To operate on the original array within the function and assign/change the values of elements, you must dereference the pointer-to-array. If you look above, that would be:
(*a)[i][j] = (i + 1) * (j + 1);
Where the parenthesis around (*a) are required due to C operator precedence.
Declaring a short prn_arr function to print the results you could do something like the following:
#include <stdio.h>
#define ROWS 3
#define COLS ROWS
void mod_arr (int (*a)[ROWS][COLS])
{
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
(*a)[i][j] = (i + 1) * (j + 1);
}
void prn_arr (int a[ROWS][COLS])
{
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++)
printf (" %2d", a[i][j]);
putchar ('\n');
}
}
int main (void) {
int a[ROWS][COLS] = {{0}};
mod_arr (&a);
prn_arr (a);
}
Where in main() above, you simply declare the array and initialize the values all zero and then pass the address to mod_arr for manipulation of the array, and then call prn_arr to output the results -- needing only to pass the array itself (it being a pointer to the first ROW of values).
However, keep in mind for large arrays, it is more efficient to pass a pointer to the array as a parameter as opposed to passing a complete copy of the array (e.g. a pointer is 8-bytes on x86_64 regardless of the size of the array, while, take for example, a 1000x1000 array which would require 1,000,000 times the size of the element bytes to copy)
Example Use/Output
$ ./bin/modarr
1 2 3
2 4 6
3 6 9
So you can see, by passing the array by-address to your function, the function receives the original address for the array (and not merely a copy of the array as some new address), so the changes made in mod_arr are changes made to the addresses within the original array itself and will be seen back in the calling function.
Look things over and if you have further questions, let me know. This is kind of a core issue when working with pointers and arrays -- understanding the types involved and the syntax for those type that allow you to make it all work.
回答2:
If you pass a variable by-value to a function the function will not modify this variable, if you pass a variable by-reference (like the pointer to arr in your case) the function will modify the variable :
void f(int a)
{
a = a+2; // or equivalently a+=2
}
will not modify a (pass-by-value)
while
void f(int* a)
{
a* = (*a)+2; // or equivalently (*a)+=2
}
will modify a (pass-by-reference)
The background is that functions have their own local scope that in case of pass-by-value can be left by a return however the function above returns void so it does not modify anything outside its local scope (https://www.geeksforgeeks.org/scope-rules-in-c/)
In C an array can be passed by value like in https://www.geeksforgeeks.org/pass-array-value-c/
If you pass the array by reference (using pointers) you can modify the array directly in the function without need of copying something
You can test this with the following :
#include <stdio.h>
void f1(int a) // pass-by-value
{
a+=2;
}
void f2(int* a) // pass-by-reference (pointer)
{
(*a)+=2;
}
int main(int argc, char argv[])
{
int a=0;
f1(a);
printf("a=%i \n",a);
a=0;
f2(&a);
printf("a=%i \n",a);#
return 0;
}
来源:https://stackoverflow.com/questions/60088406/copying-pointers-and-memory-allocation-confusion