如何在 C 中 return 2 个一维数组从函数到主函数
How to return 2 1D arrays from function to main in C
#include <stdio.h>
int *func()
{
int *a=malloc(5);
int *b=malloc(5);
for(int i=0;i<5;i++)
{
a[i]=i+1;
b[i]=i+5;
}
int *l= malloc(2);
l[0]=a;
l[1]=b;
//printf("%p %p ",l[0],l[1]);
return l;
}
int main()
{
int *k=func();
}
对于上面的代码,如何returna,b数组到main函数?
在为两个数组 a 和 b 赋值后,我将它们的地址赋给了新数组 l。现在 return 将 l 转到 main 后,如何在 main 函数中绘制数组 a 和 b 的值?
您可以通过以下方式进行
struct Array
{
int a[5];
int b[5];
};
struct Array func( void )
{
struct Array a =
{
{1,2,3,4,5},
{1,2,3,4,5}
};
return a;
}
int main( void )
{
struct Array a = func();
//...
}
另一种方法是动态分配数组,return 指针通过输出参数从函数分配数组。例如
#include <stdio.h>
#include <stdlib.h>
void func( int **a, size_t *n1, int **b, size_t *n2 )
{
*n1 = 5;
*a = malloc( sizeof( int ) * *n1 );
if ( *a != NULL )
{
int value = 1;
for ( size_t i = 0; i < *n1; i++ )
{
( *a )[i] = value++;
}
}
*n2 = 5;
*b = malloc( sizeof( int ) * *n2 );
if ( *b != NULL )
{
int value = 1;
for ( size_t i = 0; i < *n2; i++ )
{
( *b )[i] = value++;
}
}
}
int main(void)
{
int *a = NULL;
int *b = NULL;
size_t n1 = 0;
size_t n2 = 0;
func( &a, &n1, &b, &n2 );
//...
free( a );
free( b );
return 0;
}
void func(int **aa, int **bb)
{
static int a[5]={1,2,3,4,5};
static int b[5]={1,2,3,4,5};
*aa = a;
*bb = b;
}
void func2(int **aa, int **bb)
{
int *a = malloc(5 * sizeof(*a));
int *b = malloc(5 * sizeof(*b));
memcpy(a, (int []){1,2,3,4,5}, 5 *sizeof(*a));
memcpy(b, (int []){1,2,3,4,5}, 5 *sizeof(*b));
*aa = a;
*bb = b;
}
typedef struct
{
int a[5];
int b[5];
}mydata;
mydata func1(void)
{
mydata d = { .a = {1,2,3,4,5}, .b = {1,2,3,4,5}};
/* ... */
return d;
}
第二种方法非常昂贵,因为正在通过(在大多数实现中)堆栈复制整个结构。
用法示例:
int main(void)
{
int *a,*b;
func2(&a, &b);
for(size_t i = 0; i < 5; i++)
{
printf("a[%zu] = %d, b[%zu]=%d\n", i, a[i], i, b[i]);
}
}
C 中的函数只能 return 一个单一的事物 - 那个事物可以是具有多个属性的 struct
,但你不能 return 并像在 Python 或 Perl 中那样分配多个独立项。
如果调用者需要函数中的几个独立项目,那么您将需要使用多个输出参数 - 调用者必须传递指向它希望函数更新的事物的指针,而函数更新所指向的事物:
bool f( T *a, T *b ) // for some arbitrary type T
{
/**
* The *expressions* *a and *b have type T; writing to *a
* and *b in f is equivalent to writing to x and y in main.
*/
*a = new_T_value(); // writes a new value to the thing a points to
*b = another_new_T_value(); // writes a new value to the thing b points to
return some_boolean_value();
}
int main( void )
{
T x, y; // for some arbitrary type T
if ( f( &x, &y ) ) // f will write new values to x and y
do_something();
...
}
我们可以用指针类型 P *
替换 T
,这给我们:
bool f( P **a, P **b ) // for some arbitrary type P
{
/**
* The expressions *a and *b have type P *; writing to *a and *b
* in f is equivalent to writing to x and y in main.
*/
*a = new_Pstar_value(); // writes a new value to the thing a points to
*b = another_new_Pstar_value(); // writes a new value to the thing b points to
return some_boolean_value();
}
int main( void )
{
P *x, *y; // for some arbitrary type T
if ( f( &x, &y ) ) // f will write new values to x and y
do_something();
...
}
语义完全相同 - 我们希望函数 f
将新值写入 x
和 y
,因此我们必须将指针传递给 x
和 y
作为参数。只是在这种情况下 x
和 y
已经有一个指针类型 (P *
),所以我们最终将指针传递给指针 (P **
).
这是最直接的方法,需要对现有代码进行最少的更改:
#include <stdio.h>
#include <stdlib.h> // need this for malloc
/**
* We want func to dynamically allocate arrays of int and
* assign the resulting pointers to *a and *b. We also want
* to dynamically allocate and return an array of int *.
*/
int **func( int **a, int **b)
{
/**
* malloc(5) allocates 5 *bytes*, not 5 ints.
* We need to multiply the number of things we
* want by the size of each thing.
*/
*a=malloc(5 * sizeof **a); // sizeof **a == sizeof (int)
*b=malloc(5 * sizeof **b);
for(int i=0;i<5;i++)
{
/**
* The postfix [] operator has higher precedence than the
* unary * operator; we don't want to dereference a[i] and
* b[i], we want to index into what a and b *point to*, so
* we must explicitly group the * operator with the variable
* name.
*/
(*a)[i]=i+1;
(*b)[i]=i+5;
}
/**
* Each l[i] holds a value of type int *,
* so l needs to have type int **
*/
int **l= malloc(2 * sizeof *l);
l[0]=*a;
l[1]=*b;
//printf("%p %p ",l[0],l[1]);
return l;
}
int main( void )
{
int *a, *b;
int **k=func( &a, &b );
}
#include <stdio.h>
int *func()
{
int *a=malloc(5);
int *b=malloc(5);
for(int i=0;i<5;i++)
{
a[i]=i+1;
b[i]=i+5;
}
int *l= malloc(2);
l[0]=a;
l[1]=b;
//printf("%p %p ",l[0],l[1]);
return l;
}
int main()
{
int *k=func();
}
对于上面的代码,如何returna,b数组到main函数? 在为两个数组 a 和 b 赋值后,我将它们的地址赋给了新数组 l。现在 return 将 l 转到 main 后,如何在 main 函数中绘制数组 a 和 b 的值?
您可以通过以下方式进行
struct Array
{
int a[5];
int b[5];
};
struct Array func( void )
{
struct Array a =
{
{1,2,3,4,5},
{1,2,3,4,5}
};
return a;
}
int main( void )
{
struct Array a = func();
//...
}
另一种方法是动态分配数组,return 指针通过输出参数从函数分配数组。例如
#include <stdio.h>
#include <stdlib.h>
void func( int **a, size_t *n1, int **b, size_t *n2 )
{
*n1 = 5;
*a = malloc( sizeof( int ) * *n1 );
if ( *a != NULL )
{
int value = 1;
for ( size_t i = 0; i < *n1; i++ )
{
( *a )[i] = value++;
}
}
*n2 = 5;
*b = malloc( sizeof( int ) * *n2 );
if ( *b != NULL )
{
int value = 1;
for ( size_t i = 0; i < *n2; i++ )
{
( *b )[i] = value++;
}
}
}
int main(void)
{
int *a = NULL;
int *b = NULL;
size_t n1 = 0;
size_t n2 = 0;
func( &a, &n1, &b, &n2 );
//...
free( a );
free( b );
return 0;
}
void func(int **aa, int **bb)
{
static int a[5]={1,2,3,4,5};
static int b[5]={1,2,3,4,5};
*aa = a;
*bb = b;
}
void func2(int **aa, int **bb)
{
int *a = malloc(5 * sizeof(*a));
int *b = malloc(5 * sizeof(*b));
memcpy(a, (int []){1,2,3,4,5}, 5 *sizeof(*a));
memcpy(b, (int []){1,2,3,4,5}, 5 *sizeof(*b));
*aa = a;
*bb = b;
}
typedef struct
{
int a[5];
int b[5];
}mydata;
mydata func1(void)
{
mydata d = { .a = {1,2,3,4,5}, .b = {1,2,3,4,5}};
/* ... */
return d;
}
第二种方法非常昂贵,因为正在通过(在大多数实现中)堆栈复制整个结构。
用法示例:
int main(void)
{
int *a,*b;
func2(&a, &b);
for(size_t i = 0; i < 5; i++)
{
printf("a[%zu] = %d, b[%zu]=%d\n", i, a[i], i, b[i]);
}
}
C 中的函数只能 return 一个单一的事物 - 那个事物可以是具有多个属性的 struct
,但你不能 return 并像在 Python 或 Perl 中那样分配多个独立项。
如果调用者需要函数中的几个独立项目,那么您将需要使用多个输出参数 - 调用者必须传递指向它希望函数更新的事物的指针,而函数更新所指向的事物:
bool f( T *a, T *b ) // for some arbitrary type T
{
/**
* The *expressions* *a and *b have type T; writing to *a
* and *b in f is equivalent to writing to x and y in main.
*/
*a = new_T_value(); // writes a new value to the thing a points to
*b = another_new_T_value(); // writes a new value to the thing b points to
return some_boolean_value();
}
int main( void )
{
T x, y; // for some arbitrary type T
if ( f( &x, &y ) ) // f will write new values to x and y
do_something();
...
}
我们可以用指针类型 P *
替换 T
,这给我们:
bool f( P **a, P **b ) // for some arbitrary type P
{
/**
* The expressions *a and *b have type P *; writing to *a and *b
* in f is equivalent to writing to x and y in main.
*/
*a = new_Pstar_value(); // writes a new value to the thing a points to
*b = another_new_Pstar_value(); // writes a new value to the thing b points to
return some_boolean_value();
}
int main( void )
{
P *x, *y; // for some arbitrary type T
if ( f( &x, &y ) ) // f will write new values to x and y
do_something();
...
}
语义完全相同 - 我们希望函数 f
将新值写入 x
和 y
,因此我们必须将指针传递给 x
和 y
作为参数。只是在这种情况下 x
和 y
已经有一个指针类型 (P *
),所以我们最终将指针传递给指针 (P **
).
这是最直接的方法,需要对现有代码进行最少的更改:
#include <stdio.h>
#include <stdlib.h> // need this for malloc
/**
* We want func to dynamically allocate arrays of int and
* assign the resulting pointers to *a and *b. We also want
* to dynamically allocate and return an array of int *.
*/
int **func( int **a, int **b)
{
/**
* malloc(5) allocates 5 *bytes*, not 5 ints.
* We need to multiply the number of things we
* want by the size of each thing.
*/
*a=malloc(5 * sizeof **a); // sizeof **a == sizeof (int)
*b=malloc(5 * sizeof **b);
for(int i=0;i<5;i++)
{
/**
* The postfix [] operator has higher precedence than the
* unary * operator; we don't want to dereference a[i] and
* b[i], we want to index into what a and b *point to*, so
* we must explicitly group the * operator with the variable
* name.
*/
(*a)[i]=i+1;
(*b)[i]=i+5;
}
/**
* Each l[i] holds a value of type int *,
* so l needs to have type int **
*/
int **l= malloc(2 * sizeof *l);
l[0]=*a;
l[1]=*b;
//printf("%p %p ",l[0],l[1]);
return l;
}
int main( void )
{
int *a, *b;
int **k=func( &a, &b );
}