简体   繁体   English

如何在C中返回三个3d数组?

[英]How to return three 3d arrays in C?

I'm trying to write a C function to perform some vector calculations and generate three separate 3d arrays . 我试图编写一个C函数来执行一些矢量计算并生成三个单独的3d arrays I allocate the arrays at the beginning of the function 我在函数的开头分配arrays

double fac_x[Ny][Nx][Nz];
double fac_y[Ny][Nx][Nz];
double fac_z[Ny][Nx][Nz];

then fill them in with calculated values. 然后用计算值填充它们。

How can I return all three of these arrays? 如何返回所有这三个数组? What does the function prototype need to look like? 函数原型需要什么样?

There is a couple of options : 有两种选择:

  • Create a struct to hold those arrays and return it 创建一个结构来保存这些数组并返回

  • Pass pointers to those arrays and modify them without returning anything 将指针传递给那些数组,并在不返回任何内容的情况下修改它们

  • (Not elegant) Return array of those arrays (不优雅)返回这些数组的数组

  • (Not elegant) Make some global variables and modify them (不美观)制作一些全局变量并对其进行修改

There are two ways you can follow to return your arrays. 您可以按照两种方式返回数组。

  1. Make a Structure with your three arrays and return the structure 用三个数组创建一个结构并返回该结构
  2. Pass the reference to the three arrays in the function. 将引用传递给函数中的三个数组。

You can't return more than one value at a time in C, so your choices are: 在C中一次不能返回多个值,因此您的选择是:
1) Access them globally. 1)全局访问它们。
2) Send references (pointers) into the function. 2)发送引用(指针)到函数中。
3) Make all three of them into one struct and return that. 3)将所有三个都变成一个结构并返回该结构。

Do yourself a favour, and implement 3D arrays as 帮自己一个忙,并实现3D数组

  double *fac_x = malloc(Nx * Ny * Nz * sizeof(double));

  fac_x[z*Ny*Nx + y * Nx + x] = 123.0;

Now all the syntactical complications fall away. 现在,所有语法复杂性都消失了。 You still need to return three double *s, which entails taking double **s as parameters. 您仍然需要返回三个double * s,这需要将double **作为参数。 That's tolerable. 可以容忍 double **** parameters are not. 双****参数不是。

Returning a non static array (1D, 2D or 3D) from a function results in troubles because those arrays haves local scope, you can use dynamic memory, in this case a pointer to a 3D array: 从函数返回非静态数组(1D,2D或3D)会导致麻烦,因为这些数组具有局部作用域,因此可以使用动态内存,在这种情况下,将指向3D数组的指针:

#include <stdio.h>
#include <stdlib.h>

void *func(void)
{
    double (*ptr)[3][4][5] = calloc(3, sizeof *ptr);

    if (ptr == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    ptr[0][0][0][0] = 1.1;
    ptr[1][1][1][1] = 2.2;
    ptr[2][2][2][2] = 3.3;
    return ptr;
}

int main(void)
{
    double (*ptr)[3][4][5] = func();

    printf("%f\n", ptr[0][0][0][0]);
    printf("%f\n", ptr[1][1][1][1]);
    printf("%f\n", ptr[2][2][2][2]);
    free(ptr);
    return 0;
}

The only way to actually return an array is to return a structure or union type with that array as a member. 实际返回数组的唯一方法是返回以该数组作为成员的结构或联合类型。 This involves copying the array contents, which could present an efficiency problem. 这涉及复制阵列内容,这可能会带来效率问题。 More importantly, however, this is viable only if the array dimensions (your Nx , Ny , and Nz ) are compile-time constants. 但是,更重要的是,仅当数组维(您的NxNyNz )是编译时常量时,这才可行。 Example: 例:

#define Nx 5
#define Ny 7
#define Nz 10

struct arrays {
    double fac_x[Ny][Nx][Nz];
    double fac_y[Ny][Nx][Nz];
    double fac_z[Ny][Nx][Nz];
};

struct arrays foo() {
    struct arrays rval;

    // ... fill in the elements of rval ...

    return rval;
}

Otherwise, you cannot return arrays at all. 否则,您将根本无法返回数组。 You could return a struct or array of pointers to the arrays or to their first elements (provided again that at least the last two dimensions are compile-time constants), but although that might serve your purpose, it is not the same thing. 您可以返回指向数组或其第一个元素的结构或指针数组(再次提供至少最后两个维是编译时常量),但这虽然可以达到您的目的,但这并不是一回事。

More importantly, the arrays you are declaring in your function have lifetime limited to the scope in which they are declared. 更重要的是,您在函数中声明的数组的生命周期仅限于声明它们的范围。 Although you can obtain and even return a pointers to or into them, such pointers will be invalid after the function returns. 尽管您可以获取甚至返回指向它们的指针 ,但是在函数返回后, 此类指针将无效

If you want to allocate space inside your function whose lifetime extends past the function's return, you need dynamic allocation via malloc() or calloc() . 如果要在函数寿命内分配超出其返回时间的空间,则需要通过malloc()calloc()动态分配。 Supposing that you want to give the caller access to the allocated space, I recommend using output parameters (pointers) to convey the information back. 假设您想让调用者访问分配的空间,我建议使用输出参数(指针)将信息传递回去。 Example: 例:

int foo(unsigned Nx, unsigned Ny, unsigned Nz, double(*fac_x)[Nx][Nz],
        double(*fac_y)[Nx][Nz], double(*fac_z)[Nx][Nz]) {
    double (*tx)[Nx][Nz] = malloc(Ny * sizeof(*tx));

    if (!tx) {
        return -1;
    }

    double (*ty)[Nx][Nz] = malloc(Ny * sizeof(*ty));

    if (!ty) {
        free(tx);
        return -1;
    }

    double (*tz)[Nx][Nz] = malloc(Ny * sizeof(*tz));

    if (!tz) {
        free(tx);
        free(ty);
        return -1;
    }

    // ... fill tx, ty, and tz ...

    // supposing no errors have occurred:
    fac_x = tx;
    fac_y = ty;
    fac_z = tz;
    return 0;
}

This would be called like so: 就像这样:

int caller(unsigned Nx, unsigned Ny, unsigned Nz) {
    if (Nx == 0 || Ny == 0 || Nz == 0) {
        // error: invalid dimensions
        return -1;
    }

    // Note: these are pointers to arrays, not arrays themselves.
    double (*fac_x)[Nx][Nz];
    double (*fac_y)[Nx][Nz];
    double (*fac_z)[Nx][Nz];

    if (foo(Nx, Ny, Nz, fac_x, fac_y, fac_z)) {
        // handle error ...
    }

    // We are now responsible for freeing fac_x, fac_y, and fac_z

    // do stuff ... with fac_x[p][q][r], etc. ...
}

There could be multiple solutions: 可能有多种解决方案:

USING 4D-ARRAY RETURN 使用4D数组返回

double**** getArrays();

USING 4D-ARRAY OUTPUT PARAMETERS: 使用4D阵列输出参数:

Signature: 签名:

void getArrays(double****, double****, double****)

Calling: 呼叫:

double*** array1 = NULL;
double*** array2 = NULL;
double*** array3 = NULL;
void getArrays(&array1, &array2, &array3)

USING Structure: 使用结构:

typedef struct{
  double*** array1;
  double*** array2;
  double*** array3;
} MyStruct;

MyStruct getArrays(); //prototype 1
void getArrays(MyStruct*) //prototype 2

USING 2D VOID POINTER OUTPUT PARAMETERS: (if passing 4D parameters is not convenient) 使用2D VOID指针输出参数:(如果不方便传递4D参数)

Signature: 签名:

void getArrays(void**, void**, void**)

Calling: 呼叫:

void* array1 = NULL;
void* array2 = NULL;
void* array3 = NULL;
void getArrays(&array1, &array2, &array3)
double*** ar1 = (double***)array1;
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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