简体   繁体   English

复制指针和内存分配混乱

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM