代码之家  ›  专栏  ›  技术社区  ›  Nope

C:在二维数组中交换值的函数

  •  0
  • Nope  · 技术社区  · 16 年前

    我试图编写一个函数来交换二维数组中的两个元素:

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

    但是,当我尝试编译它(gcc)时,我会收到以下错误消息:

    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
    

    为了让一个二维数组作为函数参数,我需要做一些特殊的魔术吗?

    谢谢你的帮助。如果您知道数组作为函数参数的任何好的引用,请按我的方式发送它们:)

    5 回复  |  直到 16 年前
        1
  •  6
  •   DigitalRoss    16 年前

    只需声明数组参数。更好的是,对初始声明和函数的形参都使用typedef。

    问题是,在不知道行大小(即列数)的情况下,它无法计算指针调整以获得后续行。有趣的是,它不需要知道您有多少行。

    例如,这是可行的:

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

    但最好将调用方的类型和函数的类型联系在一起。


    每个子脚本访问都需要一个乘法,但这是有效的(只有符合C99的编译器)。

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

    另一个示例,即使在C89之前的环境中也可以使用:

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

    最后,由于变长数组是最近才出现的,传统的也是最快的技术是通过 int *a[] . 这不需要知道行或列的长度,但需要构造指针向量。

        2
  •  1
  •   Matthew Crumley    16 年前

    如果数组是“实”二维数组,则需要指定除第一个维度以外的所有维度的大小:

    void swap(int surface[][NUMBER_OF_COLUMNS], int x1, int y1, int x2, int y2) {
        ...
    }
    

    这有一些潜在的问题。如果你的二维数组真的是指针数组( int *surface[] )不起作用,您需要更改 surface 指向指针的指针的参数:

    void swap(int **surface, int x1, int y1, int x2, int y2) {
        ...
    }
    

    或者,为了使函数更通用,可以将其更改为接受两个int指针(可以指向任何地方)并交换它们:

    void swap(int *a, int *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    

    你可以这样称呼它:

    swap(&surface[x1][y1], &surface[x2][y2]);
    
        3
  •  1
  •   shf301    16 年前

    在C语言中,只允许未指定数组的第一维,因为它需要知道如何计算偏移量。如果需要在数组中使用可变大小的二维数组pass作为int*,请自己传递第二个维度的大小和指针数学:

    void swap(int *surface, int ySize, int x1, int y1, int x2, int y2) {
        int temp = *(surface + ySize * x1 + y1) ;
        *(surface + ySize * x1 + y1) = *(surface + ySize * x2 + y2);
        *(surface + ySize * x2 + y2) = temp;
    }
    

    这与[[]语法所做的相同,因为C中的数组实际上只是指针。

        4
  •  1
  •   sambowry    16 年前

    gcc允许可变长度数组作为函数的参数:

    #include <stdio.h> 
    
    void swap(int size; int surface[][size], int size, int x1, int y1, int x2, int y2) {
      int temp = surface[x1][y1];
      surface[x1][y1] = surface[x2][y2];
      surface[x2][y2] = temp;
    }
    
    int s[10][10];
    
    int main(){
      s[1][1] = 11;
      s[2][2] = 22;
    
      printf("s[1][1]: %i   s[2][2]: %i\n", s[1][1], s[2][2] );
      swap( s, 10, 1, 1, 2, 2 );
      printf("s[1][1]: %i   s[2][2]: %i\n", s[1][1], s[2][2] );
    
      return 0;
    }
    
        5
  •  1
  •   John Bode    16 年前

    将多维数组作为函数参数传递会带来一些麻烦。记住,在大多数上下文中,数组类型的表达式将隐式转换为指针类型,其值将是数组第一个元素的地址。例如,一个10x20的int数组将被转换为指向一个20元素的int数组的指针:

    void swap(int (*surface)[20], size_t rows, size_t x1, size_t x2, 
              size_t y1, size_t y2)
    {
      int temp;
      assert(x1 < rows && x2 < rows);
      temp = surface[x1][y1];
      surface[x1][y1] = surface[x2][y2];
      surface[x2][y2] = temp;
    }
    int main(void)
    {
      int surface[10][20];
      ...
      swap(surface, 10, 1, 1, 2, 2);
      ...
    }
    

    这就是出现大问题的地方。基于它的原型,swap()只能处理nx20 int数组;行的数量可以变化,但列的数量不能,因为 T (*)[N] 不同于 T (*)[M] 哪里有N!=m。理想情况下,您需要一个可以处理任意行数的函数 柱。实现这一点的一种方法是将数组视为t的一维数组,并手动计算行和列的偏移量:

    void swap(int *surface, size_t rows, size_t cols, size_t x1, 
              size_t x2, size_t y1, size_t y2)
    {
      int temp;
      assert(x1 < rows && x2 < rows && y1 < cols && y2 < cols);
      temp = surface[x1*cols+y1];
      surface[x1*cols+y1] = surface[x2*cols+y2];
      surface[x2*cols+y2] = temp;
    }
    int main(void)
    {
      int surface[10][20];
      ...
      swap(&surface[0][0], 10, 20, 1, 1, 2, 2);
    }
    

    在这里,我们传递第一个元素的地址(&surface[0][0]),并将其视为指向int的简单指针。这样,我们可以处理任意数量的行和列。注意,这只适用于实际的二维数组(而不是指针数组),因为swap假定数组元素是连续排列的。

    推荐文章