C语言-如何将二维数组作为函数参数传递?

12

一个人可以很容易地定义一个接受一个1d数组参数的函数,就像这样:

int MyFunction( const float arr[] )
{    
    // do something here, then return...

    return 1

}

尽管像这样的定义: int MyFunction( const float* arr ) 也可以工作。

如何定义接受 2D 数组 参数的函数呢?

我知道这个可以工作: int MyFunction( const float** arr ) -- 但是,是否可能使用第一种使用 [] 的变体?


float **arr虽然看起来像是一个二维数组,但实际上并不是。 - R.. GitHub STOP HELPING ICE
谢谢。那我该如何定义一个可以接受 2d 数组的函数? - user3262424
“2d数组”是一个模糊的名称,它可以用来指代几种不同的C语言结构。请给我们展示一个声明。 - n. m.
看我的答案。请注意,这取决于C99。如果第二个维度是一个常量,你可以直接写出这个常量,然后你的代码也可以在旧版本的C中工作。 - R.. GitHub STOP HELPING ICE
5个回答

34
在C99中,您可以在传递数组之前提供其维度:
 void array_function(int m, int n, float a[m][n])
 {
      for (int i = 0; i < m; i++)
          for (int j = 0; j < n; j++)
              a[i][j] = 0.0;
 }


 void another_function(void)
 {
     float a1[10][20];
     float a2[15][15];
     array_function(10, 20, a1);
     array_function(15, 15, a2);
 }

8
顺便提一下,第一个维度实际上是不必要的。编译器会忽略它。 - R.. GitHub STOP HELPING ICE
Jonathan,谢谢。根据你的回答,上面的原型是否适用于1d数组void array_function(int n, float a[n]) - user3262424
1
@user326424:是的,您可以按照建议将其调整为1D数组。 不过,您能获得多少收益取决于R..的评论。 - Jonathan Leffler
@R 这是否意味着内部数组或外部数组的大小未定义? - anon
@QPaysTaxes:指定 int a[][23] 表示您有一个未知长度的数组,其中数组的每个元素都是已知大小的数组。 - Jonathan Leffler
显示剩余2条评论

6

尝试像这样实现:

int MyFunction(size_t ncols, const float arr[][ncols])
{    
    // ...
}

你的回答应该注明这是C99特定的结构。 - Oliver Charlesworth
1
对我和许多人来说,“C”表示编写时的C标准的当前版本,即C99。但是,是的,需要注意,这确实需要C99。就像我在原始帖子中的评论中所述,如果“ncols”是一个常量,您可以在C99之前的C中执行相同的操作。 - R.. GitHub STOP HELPING ICE
你确定关于 C99 之前的事情吗?你是指如果 ncolsconst size_t,还是说你在谈论其他事情? - Oliver Charlesworth
1
我所说的是,如果ncols是一个整数常量表达式,比如42或者sizeof(int)。在C语言中,被const修饰的变量并不是常量。 - R.. GitHub STOP HELPING ICE
当然可以,但那与你上面提出的不同! - Oliver Charlesworth

3
当我们将2D数组作为函数参数传递时,可以选择不指定最左边的维度。关键点是,当函数中进行任何更改时,这些更改会反映在调用函数中,因为当我们将2D数组作为参数传递时,实际上函数接收到的是指向1D数组的指针。而该指针的大小为列数。 示例:
1- int funct(int (*a) [4]); 这里a是整数数组的指针。 我们也可以像这样简单地传递:
2- void funct(int a[][4]); 就像之前提到的,最左边的部分始终是可选的。 在第一个例子中,a的大小为4,因为它通常只是一个指针。 而*a的大小将为16,因为我们有4列,对于每列我们有4个字节,所以4*4 = 16字节。
但是,最好的方法始终是使用动态内存分配。
希望您能理解。

0

一种hackish的方法是传递第一个元素并手动进行数组计算。

这个较长的示例使用宏来半自动地提取数组维度以在调用中使用。

struct font { int disp, trig; };
struct font font3[3][3];
#define dim(x) (sizeof(x)/sizeof*(x))
#define font_and_dims(x) (struct font *)x, dim(x), dim(*x)
int print(char *s, struct font *font, int dimy, int dimx) { ... }

main(){ ...   print(*av, font_and_dims(font3));   ... }

调用的函数使用了费力的方式访问数组。

print(){ ...   font[row*dimx+col]   ... }

不要害怕向下滚动:好东西在底部!顶部的这个丑陋而又迂腐的函数提供了最终的字符集可移植性;但我承认它确实是一个眼酸。
#include <stdio.h>
#include <string.h>

int ao(int c) {
    switch(c) {
    case '0':return 0;
    case '1':return 1;
    case '2':return 2;
    case '3':return 3;
    case '4':return 4;
    case '5':return 5;
    case '6':return 6;
    case '7':return 7;
    case '8':return 8;
    case '9':return 9;
    case 'A':case 'a':return 10;
    case 'B':case 'b':return 11;
    case 'C':case 'c':return 12;
    case 'D':case 'd':return 13;
    case 'E':case 'e':return 14;
    case 'F':case 'f':return 15;
    default:return -1;
    }
}

enum {
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    E = 1 << 4,
    F = 1 << 5,
    G = 1 << 6,
    H = 1 << 7 };

int seg[] = {
    /*0*/ A|B|C|D|E|F,
    /*1*/   B|C,
    /*2*/ A|B|  D|E|  G,
    /*3*/ A|B|C|D|    G,
    /*4*/   B|C|    F|G,
    /*5*/ A|  C|D|  F|G,
    /*6*/ A|  C|D|E|F|G,
    /*7*/ A|B|C,
    /*8*/ A|B|C|D|E|F|G,
    /*9*/ A|B|C|    F|G,
    /*A*/ A|B|C|D|E|  G, /*A|B|C|  E|F|G,*/
    /*b*/     C|D|E|F|G,
    /*C*/       D|E|  G, /*A|    D|E|F,*/
    /*d*/   B|C|D|E|  G,
    /*E*/ A|B|  D|E|F|G, /*A|    D|E|F|G,*/
    /*F*/ A|      E|F|G,
};

struct font {
    int disp, trig;
};
/* _
  |_|
  |_|
*/
struct font font3[3][3] = {
    { {  0,0}, {'_',A}, {  0,0} },
    { {'|',F}, {'_',G}, {'|',B} },
    { {'|',E}, {'_',D}, {'|',C} },
};
/* ___
  |   |
  |___|
  |   |
  |___|
*/
struct font font5[5][5] = {
    { {  0,0}, {'_',A}, {'_',A}, {'_',A}, {  0,0} },
    { {'|',F}, {  0,0}, {  0,0}, {  0,0}, {'|',B} },
    { {'|',F}, {'_',G}, {'_',G}, {'_',G}, {'|',B} },
    { {'|',E}, {  0,0}, {  0,0}, {  0,0}, {'|',C} },
    { {'|',E}, {'_',D}, {'_',D}, {'_',D}, {'|',C} }
};
/* ____
  |    |
  |    |
  |    |
  |____|
  |    |
  |    |
  |    |
  |____|
*/
struct font font9[9][7] = {
    { {  0,0}, {'_',A}, {'_',A}, {'_',A}, {'_',A}, {  0,0}, {0,0} },
    { {'|',F}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',B}, {0,0} },
    { {'|',F}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',B}, {0,0} },
    { {'|',F}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',B}, {0,0} },
    { {'|',F}, {'_',G}, {'_',G}, {'_',G}, {'_',G}, {'|',B}, {0,0} },
    { {'|',E}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',C}, {0,0} },
    { {'|',E}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',C}, {0,0} },
    { {'|',E}, {  0,0}, {  0,0}, {  0,0}, {  0,0}, {'|',C}, {0,0} },
    { {'|',E}, {'_',D}, {'_',D}, {'_',D}, {'_',D}, {'|',C}, {0,0} },
};

#define dim(x) (sizeof(x)/sizeof*(x))
#define font_and_dims(x) (struct font *)x, dim(x), dim(*x)

int print(char *s, struct font *font, int dimy, int dimx) {
    int row, col;
    char *sp;
    for (row = 0; row < dimy; row++) {
    for (sp = s; *sp; sp++) {
        for (col = 0; col < dimx; col++) {
            putchar( seg[ao(*sp)] & font[row*dimx+col].trig ?
                font[row*dimx+col].disp : ' ');
        }
    }
    putchar('\n');
    }
}

int main(int ac, char **av) {
    enum { F1, F2, F3 } fz = F1;
    for (++av,--ac;ac;ac--,av++) {
    if (av[0][0] == '-') {
        switch (av[0][1]) {
            case '1': fz=F1; continue;
            case '2': fz=F2; continue;
            case '3': fz=F3; continue;
            default: fprintf(stderr, "Unrecognized Option!\n");
        }
    }
    if (strspn(*av, "0123456789abcdefABCDEF") != strlen(*av))
        fprintf(stderr, "Hex only!\n");
    else
        switch(fz) {
            case F1: print(*av, font_and_dims(font3)); break;
            case F2: print(*av, font_and_dims(font5)); break;
            case F3: print(*av, font_and_dims(font9)); break;
            default: fprintf(stderr, "Invalid Font!\n");
        }
    }

    return 0;
}

-2

在 C89 中,你可以使用

typedef float OneRow[2];

void func(OneRow *arr)
{
  printf("%f",arr[1][0]);
}
...
  OneRow arr[] = {{1,2},{3,4},{5,6}};
  func(arr);
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接