【问题标题】:Passing dynamic 3D matrix to function将动态 3D 矩阵传递给函数
【发布时间】:2018-05-02 08:48:38
【问题描述】:

我有一些 3D 矩阵数据,可以这样访问:data[x][y][z]

每个维度的大小只有在运行时才知道。

我通过使用 (byte (*)[Y][Z]) malloc(…) 强制转换 malloc 来获取此数据。

当我调用这个函数时,我知道矩阵的维度,但不是在编译时。因此,我不知道如何声明我在函数中接收到这样的矩阵……

函数声明中该数据的参数类型是什么?

function(byte (*matrix)[][]) // doesn't work

【问题讨论】:

  • 你为什么不干脆做类似function(byte *ptr, int x, int y, int z) 的事情,然后根据xyz 中的function 手动计算与ptr 的偏移量?
  • 您需要告诉函数矩阵有多大(并且必须在矩阵在参数列表中之前定义大小)。假设尺寸为 X、Y、Z,则:function(int X, int Y, int Z, byte matrix[X][Y][Z])function(int X, int Y, int Z, byte (*matrix)[Y][Z]))。我会使用前者;它是明确的,即使编译器没有使用维度中的X。数组的所有非前导维度都需要大小。维度可以是变量或常量(C90 仅允许常量)。
  • 很好@JonathanLeffler,我不知道参数是逐个评估的,但是一旦评估,在下一个评估之前可用。
  • @JonathanLeffler 你知道这叫什么名字吗?我在哪里可以找到一些参考或 C 规范?
  • @babon 我可以,但我已经在使用这种抽象,所以现在需要做很多工作来改变一切。此外,我认为这是可能的,但想知道如何......总是很好学习和扩展我们对语言的熟悉程度:-)

标签: c arrays multidimensional-array dynamic-arrays


【解决方案1】:

声明函数:

function(size_t Y, size_t Z, byte matrix[][Y][Z])…

并调用它:

function(Y, Z, matrix);

C 支持可变长度数组(根据版本是可选的或必需的,但在现代编译器中很常见),但被调用的函数不会自动知道维度。您必须以某种方式将它们传递给函数,并且在其声明中,函数必须声明尺寸。

注意维度一般可以是表达式;它们不必是传递的确切参数。例如,您可以这样做:

function(size_t Y, byte matrix[][2*Y][3*Y])…

例如,当Y 为10 时,声明一个采用matrix[something][20][30] 的函数。

【讨论】:

    【解决方案2】:

    这里有一些代码来说明 3D 数组的传递。 3D 数组是一个方阵数组,它们将相乘以产生最终结果。该代码可能不是最有效的,但它确实说明传递 3D VLA 值并不难。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static void mat_copy(int x, int y, const int src[x][y], int dst[x][y]);
    static void mat_list_multiply(int x, int y, const int matlist[*][*][*], int result[*][*]);
    static void mat_multiply(int x, int y, int z, const int mat1[*][*], const int mat2[*][*], int result[*][*]);
    static void mat_print(const char *tag, int m, int n, const int matrix[*][*]);
    
    int main(void)
    {
        int matrices[][4][4] =
        {
            //random -n 48 -- -99 99 | commalist -n 4 -B 12 -b '{ ' -T ' },' -R -W 4
            {
                {   63,  -61,   36,  -27, },
                {   37,  -86,   44,  -14, },
                {   57,   10,   74,   23, },
                {  -74,  -52,  -87,   53, },
            },
            {
                {  -34,   89,  -71,   34, },
                {  -68,  -44,  -89,  -95, },
                {   -4,  -44,    2,   80, },
                {   66,  -33,  -19,  -65, },
            },
            {
                {  -64,   11,   54,   20, },
                {   -7,   75,   -7,  -98, },
                {   52,   48,  -96,   76, },
                {  -38,  -46,  -85,    4, },
            },
        };
        enum { NUM_MATRICES = sizeof(matrices) / sizeof(matrices[0]) };
        int result[4][4];
        mat_list_multiply(3, 4, matrices, result);
        for (int i = 0; i < NUM_MATRICES; i++)
        {
            char name[16];
            snprintf(name, sizeof(name), "%s[%d]", "matrices", i);
            mat_print(name, 4, 4, matrices[i]);
        }
        mat_print("result", 4, 4, result);
        return 0;
    }
    
    static void mat_copy(int x, int y, const int src[x][y], int dst[x][y])
    {
        memmove(dst, src, x * y * sizeof(src[0][0]));   // sizeof(src) is not OK
    }
    
    static void mat_list_multiply(int x, int y, const int matlist[x][y][y], int result[y][y])
    {
        int product[y][y];
        mat_copy(y, y, matlist[0], product);
        for (int i = 1; i < x; i++)
        {
            mat_multiply(y, y, y, product, matlist[i], result);
            if (i != x-1)
                mat_copy(y, y, result, product);
        }
    }
    
    static void mat_multiply(int x, int y, int z, const int mat1[x][y], const int mat2[y][z], int result[x][z])
    {
        for (int i = 0; i < x; i++)
        {
            for (int j = 0; j < z; j++)
            {
                result[i][j] = 0;
                for (int k = 0; k < y; k++)
                     result[i][j] += mat1[i][k] * mat2[k][j];
            }
        }
    }
    
    static void mat_print(const char *tag, int m, int n, const int matrix[m][n])
    {
        printf("%s (%dx%d):\n", tag, m, n);
        for (int i = 0; i < m; i++)
        {
            const char *pad = "";
            for (int j = 0; j < n; j++)
            {
                printf("%s%8d", pad, matrix[i][j]);
                pad = " ";
            }
            putchar('\n');
        }
    }
    

    输出:

    matrices[0] (4x4):
          63      -61       36      -27
          37      -86       44      -14
          57       10       74       23
         -74      -52      -87       53
    matrices[1] (4x4):
         -34       89      -71       34
         -68      -44      -89      -95
          -4      -44        2       80
          66      -33      -19      -65
    matrices[2] (4x4):
         -64       11       54       20
          -7       75       -7      -98
          52       48      -96       76
         -38      -46      -85        4
    result (4x4):
     -455910    66386 -1265422  -575600
     -509373    79435 -1545267   -14906
     -392428  -468852   -38119  -464008
      137791   727227   393114  1044774
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      相关资源
      最近更新 更多