按值传递数组
Pass an array by value
一般我们传数组的时候都是按地址调用。这意味着如果我们在 main()
之外更改数组的任何值,它将反映在 main()
.
中
所以,如果我想将数组作为函数的参数传递并在 main()
中调用它,这样函数中的任何更改都不会反映在 [=11] 中,我应该怎么做=]?
例如:
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.
}
现在我想将 abc
数组按值传递给 Foo
。
(我不确定为什么 Ryan 没有自愿提供他自己的答案,但我同意以下内容应该有效:)
#include <stdlib.h> // In header
#include <string.h>
int Foo(size_t size, int arr[])
{
// guard against bad arguments
if (arr == NULL || size <= 0)
{
return -1;
}
// create local array, since size is variable, allocate dynamically
int* arr_2 = NULL;
if ((arr_2 = malloc(n * sizeof(*arr_2)) == NULL)
{
return -1; // malloc allocation error
}
// otherwise if the size is constant:
// int arr_2[SOME_CONSTANT_SIZE];
// copy from arr to arr_2
memcpy(arr_2, arr, n * sizeof(*arr_2));
// some computation
free(arr_2);
return 0;
}
请记住,一旦我们离开 Foo
的范围,arr_2
将不复存在。此外,对于 non-primitive 个数组元素,您需要做更多的复制工作。
一般情况下,你不能。
调用者可以这样做;
int main()
{
int abc[]={5,1,2,9};
{
int temp[sizeof (abc)/sizeof (*abc)];
memcpy(temp, abc, sizeof(abc));
Foo(temp);
}
}
请记住,Foo()
不会收到有关传递的数组中元素数量的任何信息。
如果你想Foo()
做类似的事情,那么调用者不需要,有必要将元素的数量作为一个单独的参数传递。
void Foo(int arr[], size_t size) /* C99 or later */
{
int temp[size]; // VLA
memcpy(temp, arr, size*sizeof(int));
/* whatever */
}
或(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);
}
为避免内存泄漏,在第二种情况下,有必要确保函数在调用 free(temp)
.
之前不会 return
在上面的 Foo()
的两个版本中,可能需要额外的错误检查(例如检测空指针或零大小被传递,malloc()
成功等)。
可以通过将数组包装在 struct
中来实现。您可以包含一个数组大小字段,这样您就不需要显式传递此参数。这种方法的优点是避免了以后必须释放的额外内存分配。
C 已经按值将参数传递给函数,但数组标识符在大多数表达式中衰减为指针,尤其是在函数调用中。然而 struct
不会衰减为指针,而是按值传递给函数,这意味着原始结构的副本及其所有内容在函数范围内可见。如果 struct
包含一个数组,它也会被复制。请注意,如果 struct
包含一个指向动态数组 int
的指针,那么当 struct
传递给函数时会复制该指针,但相同的内存是由副本和原始指针引用。这种方法依赖于包含实际数组的 struct
。
另请注意,struct
不能包含类型不完整的成员,因此不能包含 VLA。在这里,我将全局常量 MAX_ARR
定义为 100,以提供一些 space 来处理具有相同 struct
类型的不同大小的数组。
您还可以从函数中 return struct
。我已经包含了一个示例,它修改了传递给函数的 Array
struct
,并且 returns 修改后的 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;
}
程序输出:
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
一般我们传数组的时候都是按地址调用。这意味着如果我们在 main()
之外更改数组的任何值,它将反映在 main()
.
所以,如果我想将数组作为函数的参数传递并在 main()
中调用它,这样函数中的任何更改都不会反映在 [=11] 中,我应该怎么做=]?
例如:
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.
}
现在我想将 abc
数组按值传递给 Foo
。
(我不确定为什么 Ryan 没有自愿提供他自己的答案,但我同意以下内容应该有效:)
#include <stdlib.h> // In header
#include <string.h>
int Foo(size_t size, int arr[])
{
// guard against bad arguments
if (arr == NULL || size <= 0)
{
return -1;
}
// create local array, since size is variable, allocate dynamically
int* arr_2 = NULL;
if ((arr_2 = malloc(n * sizeof(*arr_2)) == NULL)
{
return -1; // malloc allocation error
}
// otherwise if the size is constant:
// int arr_2[SOME_CONSTANT_SIZE];
// copy from arr to arr_2
memcpy(arr_2, arr, n * sizeof(*arr_2));
// some computation
free(arr_2);
return 0;
}
请记住,一旦我们离开 Foo
的范围,arr_2
将不复存在。此外,对于 non-primitive 个数组元素,您需要做更多的复制工作。
一般情况下,你不能。
调用者可以这样做;
int main()
{
int abc[]={5,1,2,9};
{
int temp[sizeof (abc)/sizeof (*abc)];
memcpy(temp, abc, sizeof(abc));
Foo(temp);
}
}
请记住,Foo()
不会收到有关传递的数组中元素数量的任何信息。
如果你想Foo()
做类似的事情,那么调用者不需要,有必要将元素的数量作为一个单独的参数传递。
void Foo(int arr[], size_t size) /* C99 or later */
{
int temp[size]; // VLA
memcpy(temp, arr, size*sizeof(int));
/* whatever */
}
或(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);
}
为避免内存泄漏,在第二种情况下,有必要确保函数在调用 free(temp)
.
在上面的 Foo()
的两个版本中,可能需要额外的错误检查(例如检测空指针或零大小被传递,malloc()
成功等)。
可以通过将数组包装在 struct
中来实现。您可以包含一个数组大小字段,这样您就不需要显式传递此参数。这种方法的优点是避免了以后必须释放的额外内存分配。
C 已经按值将参数传递给函数,但数组标识符在大多数表达式中衰减为指针,尤其是在函数调用中。然而 struct
不会衰减为指针,而是按值传递给函数,这意味着原始结构的副本及其所有内容在函数范围内可见。如果 struct
包含一个数组,它也会被复制。请注意,如果 struct
包含一个指向动态数组 int
的指针,那么当 struct
传递给函数时会复制该指针,但相同的内存是由副本和原始指针引用。这种方法依赖于包含实际数组的 struct
。
另请注意,struct
不能包含类型不完整的成员,因此不能包含 VLA。在这里,我将全局常量 MAX_ARR
定义为 100,以提供一些 space 来处理具有相同 struct
类型的不同大小的数组。
您还可以从函数中 return struct
。我已经包含了一个示例,它修改了传递给函数的 Array
struct
,并且 returns 修改后的 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;
}
程序输出:
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