C – передача массива 2d в качестве аргумента функции?

Легко определить функцию, которая принимает аргумент 1d array следующим образом:

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

Хотя такое определение, как: int MyFunction( const float* arr ) будет работать.

Как определить функцию, которая принимает аргумент 2d array ?

Я знаю, что это работает: int MyFunction( const float** arr ) – но возможно ли использовать первый вариант, который использует [] ?

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

Попробуйте что-то вроде этого:

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

когда мы передаем 2D-массив в качестве аргументов для функций, это необязательно, чтобы указать самые большие размеры. Ключевым моментом здесь является то, что любые изменения, внесенные в функции, которые изменяются, отражаются в вызывающих функциях, потому что, когда мы передаем двухмерный массив, поскольку аргументы означают фактически функции получать указатель на 1-мерный массив. И размер этого числа столбцов. Примеры

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

здесь a – указатель на массив целых чисел. мы можем просто пройти так же

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

как я сказал ранее, большинство сторон всегда являются необязательными. В первом примере размер a будет 4, потому что это обычно просто указатель. в то время как размер * a будет 16, потому что у нас есть 4 столбца, и для каждого столбца мы имеем 4 байта, так что 4 * 4 = 16 байт.

Но наиболее предпочтительным способом всегда является использование динамических распределений памяти.

Надеюсь, у тебя ясно

Хакерский способ состоял бы в том, чтобы передать первый элемент и выполнить вычисления массива вручную.

Этот длинный пример использует макрос, чтобы полуавтоматически извлекать размеры массива для использования в вызове.

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

В C89 u можете использовать

 typedef float OneRow[2]; void func(OneRow *arr) { printf("%f",arr[1][0]); } ... OneRow arr[] = {{1,2},{3,4},{5,6}}; func(arr); ... 
  • что такое использование fflush (stdin) в программировании c
  • Я могу использовать больше памяти, чем то, что я выделил с помощью malloc (), почему?
  • Почему FILE * не сохраняет адрес открытого файла
  • Разделить строку на C в каждом пробеле
  • плавать до неожиданного поведения
  • Когда рекомендуется использовать strdup (vs malloc / strcpy)
  • n & (n-1), что делает это выражение?
  • Переменные экземпляра для объектов Objective C
  • Переменные стека против переменных кучи
  • В чем смысл этой части кода? void (* signal (int sig, void (* func) (int))) (int);
  • Как я могу написать общий class контейнера, который реализует данный интерфейс в C #?
  • Давайте будем гением компьютера.