【问题标题】:How to pass a 2D array by pointer in C?如何在C中通过指针传递二维数组?
【发布时间】:2013-05-19 10:18:05
【问题描述】:

我正在学习 C,但无法将二维数组的指针传递给另一个函数,然后再打印二维数组。任何帮助,将不胜感激。

int main( void ){
    char array[50][50];
    int SIZE;

    ...call function to fill array... this part works.

    printarray( array, SIZE );
}

void printarray( char **array, int SIZE ){
    int i;
    int j;

    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}

【问题讨论】:

  • void printarray(char array[][50], int SIZE)
  • 虽然可以这样做,但最好将其转换为一维数组并使用j*SIZE+i 对其进行索引。
  • @Dave 为什么? .............................(只是填充物)
  • @kotlomoy 因为 C 的 n-D 数组语法充其量是模棱两可的,并且手动索引它会迫使您考虑内存顺序(通常对缓存性能有用)。这也意味着您将来可以无缝切换到使用动态大小的数组(通过malloc)。

标签: c arrays pointers


【解决方案1】:

char ** 不代表二维数组——它是一个指向指针的数组。如果你想传递一个二维数组,你需要改变printarray的定义:

void printarray( char (*array)[50], int SIZE )

或等效:

void printarray( char array[][50], int SIZE )

【讨论】:

  • 你能用简单的英语解释一下语法“char *array[50]”是什么意思吗?
  • 运行cdecl explain 'char (*arr)[50]' 产生declare arr as pointer to array 50 of char
  • @user1362058:不,没有复制(除了指针)。您不能将数组传递给函数;它们降级为指向其第一个元素的指针。您的问题是您的类型声明完全错误。二维数组退化为指向另一个数组的指针。
  • 很好的答案。 char (*array)[50] 声明一个名为 array 的指针,指向由 50 个 chars 组成的一维数组。我认为评论中的解释有点模棱两可,我想改进。
  • @Jarkid,前者是指向50个元素数组的指针,后者是50个指针的数组。
【解决方案2】:

main()中,变量“array”被声明为

char array[50][50];

这是一个 2500 字节的数据。当main() 的“数组”被传递时,它是一个指向该数据开头的指针。它是一个指向预期以 50 行为单位的 char 的指针。

然而在函数printarray() 中,你声明

 char **array

这里的“array”是一个指向char *pointer的指针。

@Lucus 建议 void printarray( char array[][50], int SIZE ) 有效,但它不是通用的,因为您的 SIZE 参数必须为 50。

想法: 击败(yeech)printarray()中参数数组的类型

void printarray(void *array, int SIZE ){
    int i;
    int j;
    char *charArray = (char *) array;

    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", charArray[j*SIZE + i] );
        }
        printf( "\n" );
    }
}

更优雅的解决方案是将main() 中的“数组”设为指针数组。

// Your original printarray()
void printarray(char **array, int SIZE ){
    int i;
    int j;
    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}

// main()
char **array;
int SIZE;
// Initialization of SIZE is not shown, but let's assume SIZE = 50;
// Allocate table
array = (char **) malloc(SIZE * sizeof(char*));
  // Note: cleaner alternative syntax
  // array = malloc(sizeof *array * SIZE);
// Allocate rows
for (int row = 0; row<SIZE; row++) {
  // Note: sizeof(char) is 1. (@Carl Norum)
  // Shown here to help show difference between this malloc() and the above one.
  array[row] = (char *) malloc(SIZE * sizeof(char));
    // Note: cleaner alternative syntax
    // array[row] = malloc(sizeof(**array) * SIZE);
  }
// Initialize each element.
for (int row = 0; row<SIZE; row++) {
  for (int col = 0; col<SIZE; col++) {
    array[row][col] = 'a';  // or whatever value you want
  }
}
// Print it
printarray(array, SIZE);
...

【讨论】:

  • @CarlNorum 仅仅因为它并不意味着你必须无情地用 1 替换它(或完全删除它)。 sizeof 语句可以让您的代码自我记录。
  • @Thomas,如果你想让你的代码自我记录,你可以这样做而不是多余的。例如,使用sizeof **array。那么至少如果您以后更改数据类型,您可以免费获得大小调整。
  • 数组维度在传递给函数时不需要固定;例如,一个函数可以声明为void printarray(size_t Rows, size_t cols, char array[][cols])。 (我不知道为什么它在标准中使用了 14 年之后就不为人所知了。)
  • @Eric Postpischil:用“void printarray(size_t Rows, size_t cols, char array[][cols]);”声明一个函数我的编译器失败了。这是对您建议的正确测试吗?
  • @chux:在其他人真正提供帮助之前,您需要指定“我的编译器”是什么。是海合会吗?铛?一些微软的东西?错误信息是什么?一些编译器可能默认使用旧的语言版本(例如 GCC 的 c89)或非标准版本(例如 gnu89)。对于 GCC 或 clang,尝试“-std=c99”或“-std=c1x”。对于 Microsoft 编译器,请尝试 GCC 或 clang。您是否包含&lt;stdlib.h&gt; 来定义size_t? (您可以在声明中为维度使用其他整数类型;它可以是int 而不是size_t。)
【解决方案3】:

由于 C99 支持动态大小的数组,因此以下样式更方便地传递 2-dim 数组:

void printarray( void *array0, int SIZE ){
    char (*array)[SIZE] = array0;
    int i;
    int j;
    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", array[j][i] );
        }
        printf( "\n" );
    }
}

【讨论】:

  • 这是我喜欢的答案,因为它适用于您在编译时不知道大小的情况。但是,我想做两点说明:(1.) 如果您同时传递两个维度大小(例如,行和列),那么 array 应该声明为 char (*array)[columns] = array0; (2.) 如果您使用 const 正确性 (在这种情况下,您不会更改数组中的任何值,因此它是合适的),那么您希望将array0 参数声明为const void *array0,并将array 在正文中声明为@987654327 @
  • 没有char (*array)[SIZE] = array0; 的干净替代方案是printarray(int SIZE, char array[SIZE][SIZE])
【解决方案4】:

您可以使用双指针轻松传递二维数组。

  void printarray( char **array, int n)
  {
     int i, j;
     for(i=0; i<n; i++ )
     {
         for(j=0; j<n; j++)
         {
            printf("%c ", array[i][j] );
         }
        printf( "\n" );
     }
  }

  int main()
  {
      int n = 2;
      int i, j;

      char **array = (char **) malloc(n * sizeof(char*));

      for (i=0; i<n; i++) 
      {
        array[i] = (char *) malloc(n* sizeof(char));
      }

     for (i=0; i<n; i++)
     {
       for (j=0; j<n; j++)
       {
           scanf("%c ", &array[i][j]);
       }
     }

     printarray(array, n);

     return 0;
  }

完整代码:Ideone

【讨论】:

  • 您的答案中没有数组。
猜你喜欢
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 2016-05-14
相关资源
最近更新 更多