简体   繁体   中英

C -- passing a 2d array as a function argument?

One can easily define a function that accepts a 1d array argument like this:

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

    return 1

}

Although a definition such as: int MyFunction( const float* arr ) would work as well.

How can one define a function that accepts a 2d array argument?

I know that this works: int MyFunction( const float** arr ) -- but, is it possible to use the first variation that uses [] ?

In C99, you can provide the dimensions of the array before passing it:

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

Try something like this:

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

when we pass 2D array as a arguments to the functions it's optional to specify left most dimensions.The key point here is when any changes made in functions that changes reflects in calling functions because when we pass 2-D array as a arguments means actually functions receive pointer to 1-D array. And size of that is number of columns . examples

1 - int funct(int (*a) [4]);

here a is pointer to array of integer. we can simply pass like this also

2- void funct(int a[][4]);

as I said earlier left most side is always optional. In first example size of a will be 4 because it's normally just pointer. while size of *a will be 16 because we have 4 column and for each column we have 4 bytes so 4*4 = 16 bytes.

But most preferable way is always use dynamic memory allocations.

I hope u got clear

The hackish way would be to pass the first element and do the array calculations manually.

This longish example uses a macro to semi-automatically extract the array dimensions to use in the call.

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

The called function accesses the array the hard way.

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

Don't be afraid to scroll down: the good stuff is at the bottom! This ugly, pedantic function at the top provides ultimate charset portability; but it is an eyesore, I admit.

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

In C89 u can use

typedef float OneRow[2];

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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