【问题标题】:Passing matrix to function, C将矩阵传递给函数,C
【发布时间】:2015-06-12 04:18:21
【问题描述】:

环顾四周后,我构建了一个函数,该函数接受一个矩阵并在其上执行我需要的任何操作,如下所示:

float energycalc(float J, int **m, int row, int col){
...
}

在 main 中定义并填充了数组的大小,但是我不能将其传递给函数本身:

int matrix[row][col];
...
E=energycalc(J, matrix, row, col);

这会导致编译期间出现警告

"project.c:149: 警告:从'energycalc' 传递参数 2 不兼容的指针类型 project.c:53:注意:预期为“int **”,但 参数的类型为‘int (*)[(long unsigned int)(col + -0x00000000000000001)]’

并导致分段错误。

非常感谢任何帮助,谢谢。

【问题讨论】:

  • float energycalc(float J, int row, int col, int m[row][col] ){
  • 数组数组与指向指针的指针不同,请参阅例如 this old answer of mine 了解原因。不过,您可能会使用指向数组的指针(例如int (*m)[])。
  • @legends2k 这个问题只被标记为C...当Cool Guy 抱怨我的回答时,我发现很难。
  • C 重复:2D array passing to a functionpassing 2d arrays。不用担心,我只是环顾四周就找到了 2 个,如果我们出汗更多,我们肯定可以挖掘更多 :)
  • 检查骗子,你会发现比这里发布的任何答案都更完整。

标签: c function matrix


【解决方案1】:

指针指针不是数组,也不是指向二维数组。它与数组无关,句号,所以忘记你曾经听说过指针到指针和数组一起。

(混乱可能来自于一群困惑的潜在编程教师/作者告诉每个人他们应该在分配动态二维数组时使用指针对指针。这只是一个糟糕的建议,因为它不会分配在相邻内存单元中分配的真实数组,而是在整个堆中爆炸成碎片的碎片查找表。See this 供参考,了解如何实际分配此类数组。)

假设您的编译器不是完全古老的,只需使用可变长度数组 (VLA),它是 C 语言中按照 C99 标准引入的功能。

#include <stdio.h>

void print_matrix (size_t row, size_t col, int matrix[row][col]);


int main (void)
{
  int matrix[2][3] = 
  {
    {1,2,3},
    {4,5,6}
  };

  print_matrix(2, 3, matrix);

  return 0;
}

void print_matrix (size_t row, size_t col, int matrix[row][col])
{
  for(size_t r=0; r<row; r++)
  {
    for(size_t c=0; c<col; c++)
    {
      printf("%d ", matrix[r][c]);
    }
    printf("\n");
  }
}

【讨论】:

    【解决方案2】:

    将二维数组传递给 C 中的函数通常会让新手感到困惑。
    原因是他们假设数组是指针,并且缺乏对数组如何衰减为指针的理解。
    永远记住,当作为参数传递时,数组转换为指向其第一个元素的指针
    在函数调用中

    E = energycalc(J, matrix, row, col);  
    

    matrix 被转换为指向其第一个元素 matrix[0] 的指针。这意味着传递matrix 等价于传递&amp;matrix[0]。请注意&amp;matrix[0] 的类型是int(*)[col](指向col int 数组的指针),因此是matrix。这表明函数energycalc 的第二个参数必须是int(*)[col] 类型。将函数声明改为

     float energycalc(int col, int (*m)[col], int row, float J);  
    

    并将您的函数称为

     E = energycalc(col, matrix, row, J); 
    

    【讨论】:

    • 或者干脆把指针参数声明为int m[row][col],这样可读性更好。
    • @Lundin;或int m[][col].
    • 确实如此。但我的观点是:我为什么要降低我的代码的可读性?
    • @Lundin;你为什么认为它会降低可读性?对我来说,int m[row][col] 的可读性不如 int (*m)[col]
    • 当然,他们必须学习差异,但即使是最机敏的程序员也会有她沉闷的一天,因为int(*)[col] 会比int[row][col] 更简单,更明确,而int[row][col] 只不过是参数列表中的前者.
    【解决方案3】:

    如果数组声明为

    int matrix[row][col];
    

    然后将函数声明改为

    float energycalc(float J, int m[][col], int row, int col){
    

    T 类型的二维数组的名称不会衰减为 T**

    如果col是一个局部变量,那么你需要在matrix之前调用带有col参数的函数。这样做是为了让col 在函数中可见。

    【讨论】:

    • @BLUEPIXY ,对不起,我没听懂
    • DEMOerror: 'col' undeclared here (not in a function)
    • @CoolGuy;声明float energycalc(float J, int m[][col], int row, int col) 编译器不知道col 并且会产生错误。在int m[][col] 中使用之前,您必须先放置col
    【解决方案4】:

    函数应该像这样声明

    float energycalc( float J, int row, int col, int ( *m )[col] );
    

    如果您的编译器支持可变长度数组。

    否则如果在声明中

    int matrix[row][col];
    

    col 是一些常量,那么函数可以通过以下方式声明

    float energycalc(float J, int m[][col], int row );
    

    前提是在函数之前定义了常量col

    你的函数声明

    float energycalc(float J, int **m, int row, int col);
    

    适用于声明数组的情况

    int * matrix[row];
    

    并且数组的每个元素都是动态分配的,例如

    for ( int i = 0; i < row; i++ ) matrix[i] = malloc( col * sizeof( int ) );
    

    【讨论】:

      【解决方案5】:

      我认为你可以在 C 中做这样的事情

      float function_name(int mat_width, int mat_height, float matrix[mat_width][mat_height]) {
          ... function body...
      }
      

      【讨论】:

      • 如果mat_widthmat_heigth 是编译时常量,则可以。如果它们是,它们应该用大写写(因为约定),然后这是最好的方法,因为它清楚而明确地记录了函数期望指向 N×M 矩阵的指针这一事实,而不是仅仅指向随机类型的指针,而不知道它是否是数组以及大小。
      • @Bregalad 这不是真的......你可以 mat_width 和 mat_height 可以是变量,你可以每次发送不同的值......我认为这不是标准 C,而是一个扩展。
      • @Bregalad 这些是可变长度数组 (VLA)。您可能希望将您的 C 知识更新到 16 年前发布的 C99。
      • @MattHammond 这是标准的 C.
      • @Lundin matrix 在这个答案中具有可变修改类型。它可能不指向 VLA(例如,可以从两个不同的地方调用该函数,每个地方都有一个普通数组)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      相关资源
      最近更新 更多