Передача многомерных массивов в качестве аргументов функции в C

В C могу ли я передать многомерный массив функции в качестве одного аргумента, когда я не знаю, какие размеры массива будут ?

Кроме того, мой многомерный массив может содержать типы, отличные от строк.

Метки

4 ответа

  1. Это можно сделать с любым типом данных. Просто сделайте его указателем на указатель:

    typedef struct {
      int myint;
      char* mystring;
    } data;
    
    data** array;
    

    Но не забывайте, что вам все еще нужно malloc переменная, и она становится немного сложной:

    //initialize
    int x,y,w,h;
    w = 10; //width of array
    h = 20; //height of array
    
    //malloc the 'y' dimension
    array = malloc(sizeof(data*) * h);
    
    //iterate over 'y' dimension
    for(y=0;y<h;y++){
      //malloc the 'x' dimension
      array[y] = malloc(sizeof(data) * w);
    
      //iterate over the 'x' dimension
      for(x=0;x<w;x++){
        //malloc the string in the data structure
        array[y][x].mystring = malloc(50); //50 chars
    
        //initialize
        array[y][x].myint = 6;
        strcpy(array[y][x].mystring, "w00t");
      }
    }
    

    Код для освобождения структуры выглядит похожим — не забудьте позвонить free () на все, что вы malloced! (Кроме того, в надежных приложениях вы должны проверить возврат malloc() .)

    Теперь предположим, что вы хотите передать это функции. Вы все еще можете использовать двойной указатель, потому что вы, вероятно, хотите делать манипуляции со структурой данных, а не указатель на указатели структур данных:

    int whatsMyInt(data** arrayPtr, int x, int y){
      return arrayPtr[y][x].myint;
    }
    

    Вызовите эту функцию с:

    printf("My int is %d.\n", whatsMyInt(array, 2, 4));
    

    Выход:

    My int is 6.
    
  2. Передайте явный указатель на первый элемент с измерениями массива в качестве отдельных параметров. Например, для обработки произвольного размера 2-d массивов int:

    void func_2d(int *p, size_t M, size_t N)
    {
      size_t i, j;
      ...
      p[i*N+j] = ...;
    }
    

    который будет называться как

    ...
    int arr1[10][20];
    int arr2[5][80];
    ...
    func_2d(&arr1[0][0], 10, 20);
    func_2d(&arr2[0][0], 5, 80);
    

    Тот же принцип применяется для массивов более высокой размерности:

    func_3d(int *p, size_t X, size_t Y, size_t Z)
    {
      size_t i, j, k;
      ...
      p[i*Y*Z+j*Z+k] = ...;
      ...
    }
    ...
    arr2[10][20][30];
    ...
    func_3d(&arr[0][0][0], 10, 20, 30);
    
  3. int matmax(int **p, int dim) // p- matrix , dim- dimension of the matrix 
    {
        return p[0][0];  
    }
    
    int main()
    {
       int *u[5]; // will be a 5x5 matrix
    
       for(int i = 0; i < 5; i++)
           u[i] = new int[5];
    
       u[0][0] = 1; // initialize u[0][0] - not mandatory
    
       // put data in u[][]
    
       printf("%d", matmax(u, 0)); //call to function
       getche(); // just to see the result
    }
    
  4. Вы можете объявить свою функцию как:

    f(int size, int data[][size]) {...}
    

    Компилятор выполнит всю арифметику указателей за вас.

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

    GNU C позволяет пересылать объявления аргументов (в случае, если вам действительно нужно передать измерения после массива):

    f(int size; int data[][size], int size) {...}
    

    Первое измерение, хотя и может быть передано в качестве аргумента, бесполезно для компилятора C (даже для оператора sizeof, при применении над массивом, переданным в качестве аргумента, всегда будет рассматриваться как указатель на первый элемент).