Search code examples
carraysfunction-parameter

C: Function to swap values in 2D array


I'm trying to write a function to swap 2 elements in a 2D array:

void swap(int surface[][], int x1, int y1, int x2, int y2) {
    int temp = surface[x1][y1];
    surface[x1][y1] = surface[x2][y2];
    surface[x2][y2] = temp;
}

however when I try to compile it (gcc), I get this error message:

Sim_Annealing.c: In function `swap': 
Sim_Annealing.c:7: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:9: error: invalid use of array with unspecified bounds

Is there some special magic I have to do in order to have a 2D array as a function parameter?

Thanks for your help. If you know of any good references for arrays as function parameters send them my way :)


Solution

  • Just declare the array parameters. Better yet, use a typedef for both the initial declaration and the function's formal parameter.

    The problem is that without knowing the row size, i.e., the number of columns, it has no way to compute the pointer adjustment to get subsequent rows. Interestingly, it does not need to know how many rows you have.

    For example, this works:

    void swap(int surface[][20], int x1, int y1, int x2, int y2) {
      int temp = surface[x1][y1];
        surface[x1][y1] = surface[x2][y2];
        surface[x2][y2] = temp;
    }
    

    But it would be better to tie the caller's types and the function's type together.


    Every subscript access will require a multiply, but this works (only C99-conforming compilers) ...

    int f(int, int, int a[*][*]);
    
    int f(int r, int c, int a[r][c])
    {
      return a[99][100];
    }
    

    Another example, which would work in even pre-C89 environments:

    typedef int surface_t[][20];
    
    surface_t therealthing = {
      { 1, 2, 3},
      { 4, 5, 6}
    };
    
    void swap(surface_t x) {
      x[0][2] = 'q';
    }
    
    void f1(void) {
      swap(therealthing);
    }
    

    And finally, because variable length arrays are something quite recent, the traditional and still the fastest technique is to pass int *a[]. This doesn't require any knowledge of either row or column lengths, but you do need to construct the pointer vector.