[英]copying pointers and memory allocation confusion
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? 1) arr 也会被修改吗? ie must I include the line: arr = arrCpy;
即我必须包括这一行: arr = arrCpy; or should I instead use: arr = mod_Arr(arr) //and get mod_Arr to return an array?
或者我应该使用: arr = mod_Arr(arr) //并获取 mod_Arr 来返回一个数组? 2) Must I free(arr) to prevent old values of arr taking up space?
2)我是否必须释放(arr)以防止 arr 的旧值占用空间? 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?
如果指针现在指向新内存而不是修改旧地址处的值,我是否必须清除旧地址中的无用内容?
If you have an array in main()
that is int a[3][3];
如果
main()
中有一个数组,它是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.并且您想将该数组传递给您的函数,以便可以在函数内修改它以及在调用函数(此处为
main()
)中看到的更改,您必须将数组的地址作为参数传递。 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]
.上述类型的语法为
int (*a)[3][3]
。 (eg 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: (例如
int[3][3]
的指向数组的指针)因此要传递数组的地址(它仍然按值传递地址,C 没有引用),您的函数声明将如下所示:
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 .由于C 运算符优先级,需要
(*a)
周围的括号。
Declaring a short prn_arr
function to print the results you could do something like the following:声明一个简短的
prn_arr
函数来打印结果,您可以执行以下操作:
#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).在上面的
main()
,您只需声明数组并将值初始化为零,然后将地址传递给mod_arr
以操作数组,然后调用prn_arr
输出结果——只需要传递数组本身(它是指向第一个 ROW 值的指针)。
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 (eg 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)但是,请记住,对于大型数组,将指向数组的指针作为参数传递比传递数组的完整副本更有效(例如,无论数组的大小如何,指针在 x86_64 上都是 8 字节,而例如,一个 1000x1000 的数组需要复制元素字节大小的 1,000,000 倍)
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.所以你可以看到,通过将数组按地址传递给你的函数,函数接收数组的原始地址(而不仅仅是数组的副本作为一些新地址),所以在
mod_arr
中所做的更改是对原始数组本身中的地址,并将在调用函数中看到。
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.
这是使用指针和数组时的一个核心问题——了解所涉及的类型以及这些类型的语法,使您能够使其全部工作。
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 :如果您将变量按值传递给函数,则该函数不会修改此变量,如果您通过引用传递变量(例如在您的情况下指向
arr
的指针),则该函数将修改该变量:
void f(int a)
{
a = a+2; // or equivalently a+=2
}
will not modify a
( pass-by-value )不会修改
a
( pass-by-value )
while尽管
void f(int* a)
{
a* = (*a)+2; // or equivalently (*a)+=2
}
will modify a
( pass-by-reference )将修改
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/ )背景是函数有自己的局部范围,在按值传递的情况下,
return
值可以留下,但是上面的函数返回void
因此它不会修改其局部范围之外的任何内容 ( 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/在 C 中,数组可以按值传递,如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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.