【问题标题】:C - Pointer to a matrixC - 指向矩阵的指针
【发布时间】:2013-01-05 04:27:15
【问题描述】:

我正在尝试通过引用将矩阵传递给函数。该函数会将矩阵的每个元素A[i][j] 替换为-A[i][j]。我首先创建矩阵:

float a[3][4] =
{
    {1.0f, 0.0f, 0.0f, 0.0f},
    {0.0f, 1.0f, 0.0f, 0.0f},
    {1.0f, 1.0f, 0.0f, 0.0f},
};

然后,我得到指向这个矩阵的指针:

float*** pa = &a;

那么,我介绍如下函数:

void process(float ***matrix, int nRows, int nCols){
 short i;
 short j;
 for (i=0 ; i<nRows; i++){
   for (j=0 ; j<nCols ; j++){
     (*matrix)[i][j] *= -1;
   }
 }
}

我称之为:

process(pa,3,4);

我的程序执行失败并返回:

Segmentation fault: 11

有什么想法吗?

答案摘要:根据本问题收到的问题的一些注释:

我。可以使用上述函数,前提是a 的初始化稍有不同,以便成为float**。特别是:

int numberOfRows = 3;
int numberOfColumns = 4;
float **a = (float **) malloc(sizeof (float *) * numberOfRows);
for (i = 0; i < numberOfRows; ++i) {
    a[i] = (float *) malloc(sizeof (float) * numberOfColumns);
}

然后,它作为process(&amp;a, 3,4); 传递给函数process

二。或者,可以使用以下功能:

void multi_by_minus(float *matrix, int nRows, int nCols) {
  short i,j;
  for (i = 0; i < nRows; i++) {
      for (j = 0; j < nCols; j++) {
          matrix[i * nCols + j] *= -1;
      }
  }
}

将矩阵视为一维数组。在这种情况下,我们只需将其调用为 multi_by_minus(&amp;a, 3, 4);

三。最后,我们可以使用方法:

void process2(int nRows, int nCols, float (*matrix)[nCols]) {
  short i, j;
  for (i = 0; i < nRows; i++) {
    for (j = 0; j < nCols; j++) {
        matrix[i][j] *= -1;
    }
  }
}

我们提供了一个指向a的指针,也就是说,我们像process2(3,4,&amp;a);一样调用它。通过这种方式,我们获得了对二维矩阵元素的访问权限。

【问题讨论】:

标签: c pointers matrix


【解决方案1】:

不需要三重指针,因为您已经提供了内存。如果你要在 de 函数中分配内存,你会使用它。

如果不提供至少一维的大小,您就无法索引二维矩阵。原因是编译器需要生成代码来访问正确的偏移量,同时考虑到这两个维度。在这种特殊情况下,我建议将一个简单的指针和索引作为一维数组传递,如下所示:

void process(float *matrix, int nRows, int nCols){
 short i;
 short j;
 for (i=0 ; i<nRows; i++){
   for (j=0 ; j<nCols ; j++){
     matrix[i * nCols + j] *= -1;
   }
 }
}

你可以这样称呼它:

process((float*)a,3,4);

这样你手动索引你的缓冲区。

【讨论】:

  • 以这种方式,我操纵(2D)矩阵,就好像它是(1D)向量一样。这是有道理的,但是,有没有办法直接使用 2D 实体?
  • 谢谢!它工作正常。还有一个问题:我查看了 BLAS,发现大多数函数都期望向量和矩阵以void* 的形式提供!那究竟是什么?它应该意味着“任何可能的类型吗?”
  • 您不必在编译时绑定大小来传递二维矩阵。请参阅我的答案以了解如何执行此操作。
【解决方案2】:

您必须将函数的签名更改为:

void process(float (*matrix)[3][4], int nRows, int nCols){

并且在调用函数时,使用这个:

process(&a, 3, 4);

【讨论】:

  • 不错,但它将matrix 绑定为固定大小。
  • 好吧,尼克的回答是处理任何大小的二维堆栈数组的唯一方法。如果你不想要一维索引,你应该使用二维堆数组(新/删除)。然后你可以使用双指针或三指针。
【解决方案3】:

如果将nCols参数放在matrix参数之前,则可以传递二维矩阵并以自然方式使用,无需额外的*运算符或索引运算:

void process(int nRows, int nCols, float (*matrix)[nCols])
{
    for (short i = 0 ; i < nRows; i++)
    {
        for (short j = 0; j < nCols; j++)
        {
            matrix[i][j] *= -1;
        }
     }
}

然后你像这样调用process

process(3, 4, matrix);

顺便说一句:

  • 除非有特殊原因要创建ij short,否则你应该声明它们intint 被定义为目标平台上整数的“自然”大小。

【讨论】:

  • 这是对 C99 功能的绝佳使用。我从没想过这样做。
【解决方案4】:

很简单,如果你有一个矩阵:

int m[2][2]={{1,0},{0,1}};

并且你想定义一个指向m的指针,所以你必须声明:

int (*mptr)[2][2];
mprt=m; // or mptr=&m;  is the same.

你可以用它来指向矩阵m的元素。

(*mptr)[i][j]....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多