按值传递数组

Fah*_*hik 11 c arrays function pass-by-value

通常当我们按名称传递数组时,它是按地址调用的.这意味着如果我们改变外部数组的任何值,main()它将被反映出来main().

那么,如果我想将数组作为函数的参数传递并在其中调用,main()以便该函数中的任何更改都不会反映在内部,我应该怎么做main()

例如:

void Foo(int arr[])   //takes an integer array `arr` as argument
{
    // do something with `arr
}

int main()
{
    int abc[]={5,1,2,9};
    //do something to pass `abc` inside `Foo` so that changes inside `Foo` doesn't change the value of `abc` array.
}
Run Code Online (Sandbox Code Playgroud)

现在我想通过值传递abc数组Foo.

ex *_*ilo 13

可以通过将数组包装在一个中来实现struct.您可以包含数组大小的字段,以便您不需要显式传递此参数.这种方法的优点是避免了以后必须释放的额外内存分配.

C已经通过值将参数传递给函数,但是数组标识符在大多数表达式中衰减为指针,特别是在函数调用中.然而,structs不会衰减到指针,而是通过值传递给函数,这意味着原始结构的副本及其所有内容在函数范围内都是可见的.如果struct包含一个数组,也会复制它.请注意,如果struct包含,例如,指向int动态数组的指针,则在struct传递给函数时复制指针,但复制和原始指针都引用相同的内存.这种方法依赖于struct包含实际数组.

另请注意,a struct不能包含具有不完整类型的成员,因此不能包含VLA.在这里,我将全局常量定义MAX_ARR为100,以便为处理具有相同struct类型的不同大小的数组提供一些空间.

您也可以struct从函数返回a .我已经包含了一个示例,它修改了Array struct传递给函数的函数,并返回修改后的函数,该函数struct被赋值给不同Array struct的函数.这导致调用者可以访问原始数组和转换后的数组.

#include <stdio.h>

#define MAX_ARR  100

struct Array {
    size_t size;
    int array[MAX_ARR];
};

void print_array(struct Array local_arr);
void func(struct Array local_arr);
struct Array triple(struct Array local_arr);

int main(void)
{
    struct Array data = {
        .size = 10,
        .array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
    };
    struct Array transformed_data;

    func(data);
    transformed_data = triple(data);

    printf("Original\n");
    print_array(data);

    printf("Transformed\n");
    print_array(transformed_data);

    return 0;
}

void print_array(struct Array local_arr)
{
    for (size_t i = 0; i < local_arr.size; i++) {
        printf("%5d", local_arr.array[i]);
    }
    putchar('\n');
}

void func(struct Array local_arr)
{
    for (size_t i = 0; i < local_arr.size; i++) {
        local_arr.array[i] *= 2;
    }
    printf("Modified\n");
    print_array(local_arr);
}

struct Array triple(struct Array local_arr)
{
    for (size_t i = 0; i < local_arr.size; i++) {
        local_arr.array[i] *= 3;
    }
    return local_arr;
}
Run Code Online (Sandbox Code Playgroud)

节目输出:

Modified
    2    4    6    8   10   12   14   16   18   20
Original
    1    2    3    4    5    6    7    8    9   10
Transformed
    3    6    9   12   15   18   21   24   27   30
Run Code Online (Sandbox Code Playgroud)


Pet*_*ter 5

一般来说,你不能.

来电者可以这样做;

int main()
{
    int abc[]={5,1,2,9};

    {
         int temp[sizeof (abc)/sizeof (*abc)];
         memcpy(temp, abc, sizeof(abc));
         Foo(temp);
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住,Foo()没有收到有关传递的数组中元素数量的任何信息.

如果你想做Foo()类似的事情,那么调用者不需要,有必要将元素的数量作为单独的参数传递.

void Foo(int arr[], size_t size)    /*  C99 or later */
{
       int temp[size];   //   VLA
       memcpy(temp, arr, size*sizeof(int));
         /* whatever */
}
Run Code Online (Sandbox Code Playgroud)

或(在C99之前).

void Foo(int arr[], size_t size)    /*  Before C99 */
{
       int *temp = malloc(size * sizeof (int));
       memcpy(temp, arr, size*sizeof(int));
         /* whatever */
       free(temp);
}
Run Code Online (Sandbox Code Playgroud)

为避免内存泄漏,在第二种情况下,必须确保函数在调用之前不返回free(temp).

Foo()上面的两个版本中,可能需要额外的错误检查(例如,检测空指针或传递的零大小,malloc()成功等).

  • 它不是mallocing堆栈数组 - 它动态分配内存来保存数组的副本.甚至不要让我开始实现不需要支持C11的VLA. (2认同)