繁体   English   中英

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

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

我试图编写一个C函数来执行一些矢量计算并生成三个单独的3d arrays 我在函数的开头分配arrays

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

然后用计算值填充它们。

如何返回所有这三个数组? 函数原型需要什么样?

有两种选择:

  • 创建一个结构来保存这些数组并返回

  • 将指针传递给那些数组,并在不返回任何内容的情况下修改它们

  • (不优雅)返回这些数组的数组

  • (不美观)制作一些全局变量并对其进行修改

您可以按照两种方式返回数组。

  1. 用三个数组创建一个结构并返回该结构
  2. 将引用传递给函数中的三个数组。

在C中一次不能返回多个值,因此您的选择是:
1)全局访问它们。
2)发送引用(指针)到函数中。
3)将所有三个都变成一个结构并返回该结构。

帮自己一个忙,并实现3D数组

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

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

现在,所有语法复杂性都消失了。 您仍然需要返回三个double * s,这需要将double **作为参数。 可以容忍 双****参数不是。

从函数返回非静态数组(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;
}

实际返回数组的唯一方法是返回以该数组作为成员的结构或联合类型。 这涉及复制阵列内容,这可能会带来效率问题。 但是,更重要的是,仅当数组维(您的NxNyNz )是编译时常量时,这才可行。 例:

#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;
}

否则,您将根本无法返回数组。 您可以返回指向数组或其第一个元素的结构或指针数组(再次提供至少最后两个维是编译时常量),但这虽然可以达到您的目的,但这并不是一回事。

更重要的是,您在函数中声明的数组的生命周期仅限于声明它们的范围。 尽管您可以获取甚至返回指向它们的指针 ,但是在函数返回后, 此类指针将无效

如果要在函数寿命内分配超出其返回时间的空间,则需要通过malloc()calloc()动态分配。 假设您想让调用者访问分配的空间,我建议使用输出参数(指针)将信息传递回去。 例:

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;
}

就像这样:

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. ...
}

可能有多种解决方案:

使用4D数组返回

double**** getArrays();

使用4D阵列输出参数:

签名:

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

呼叫:

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

使用结构:

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

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

使用2D VOID指针输出参数:(如果不方便传递4D参数)

签名:

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

呼叫:

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