通过指针传递二维数组

10

如果我不能更改foo()的代码或原型,我该如何将m矩阵传递给foo()?

void foo(float **pm)
{
    int i,j;
    for (i = 0; i < 4; i++)
        for (j = 0; j < 4; j++)
            printf("%f\n", pm[i][j]);

}

int main ()
{
    float m[4][4];

    int i,j;
    for (i = 0; i < 4; i++)
        for (j = 0; j < 4; j++)
            m[i][j] = i+j;

    foo(???m???);
}
9个回答

15

如果您坚持上述对foo的声明,即

void foo(float **pm)

使用内置的二维数组,即

float m[4][4];

那么让您的foo处理m唯一的方法是创建一个额外的“行索引”数组,并将其传递而不是m

...
float *m_rows[4] = { m[0], m[1], m[2], m[3] };
foo(m_rows);

无法直接将 m 传递给 foo,这是不可能的。参数类型 float ** 与参数类型 float [4][4] 完全不兼容。

另外,自 C99 起,可以以更紧凑的方式表达上述内容。

foo((float *[]) { m[0], m[1], m[2], m[3] });

顺便提一下,如果您仔细看的话,您会发现这基本上与Carl Norum在他的答案中所建议的是相同的。唯一不同的是,Carl使用malloc分配了数组内存,并非绝对必要。


Carl也在单独为每一行分配内存,而AndreyT的示例则将实际数据留在单个块中。 - caf

8

如果无法更改foo(),则需要更改m。将其声明为float **m,并适当分配内存。然后调用foo()。类似以下方式:

float **m = malloc(4 * sizeof(float *));
int i, j;
for (i = 0; i < 4; i++)
{
    m[i] = malloc(4 * sizeof(float));
    for (j = 0; j < 4; j++)
    {
        m[i][j] = i + j;
    }
}

不要忘记之后要调用free()函数!

你使用的技术与动态分配内存没有任何关系。由于数组大小是恒定的,因此您可以像在OP中一样将内存“分配到堆栈”上。 - AnT stands with Russia
当然可以,但这并不是错误——解决问题的方法是更改m的类型。 - Carl Norum
@Carl Norum:不一定。问题陈述似乎暗示着现有的 foo 必须与现有的 m 协同工作。解决问题的方法是更改传递给 foo 的内容类型,而不是更改 m 的类型。 - AnT stands with Russia
@AndreyT,这似乎很公平 - 我理解为只能无法更改foo() - Carl Norum
@Carl Norum:你说得对。这可能是OP所暗示的。我只是想说,转换为动态分配并不是绝对必要的。 - AnT stands with Russia

3
你做不到。 mfoo 的参数不兼容。你需要使用指针的临时数组。
int main()
{
    float m[4][4];
    int i,j;

    float *p[4];

    p[0] = m[0];
    p[1] = m[1];
    p[2] = m[2];
    p[3] = m[3];

    for (i = 0; i < 4; i++)
        for (j = 0; j < 4; j++)
            m[i][j] = i+j;


    foo(p);

2

如果你有一个支持C99的编译器,也就是当前的C标准,那么你可以这样做:

foo((float *[]){ m[0], m[1], m[2], m[3] });

请注意,这与AndreyT的答案完全相同,只是省略了命名临时数组的步骤。


2
  • you dont need to do any changes in the main,but you function will work properly if you change the formal prototype of your function to (*pm)[4] or pm[][4] because **pm means pointer to pointer of integer while (*pm)[4] or pm[][4] means pointer to poiner of 4 integers .

    m here is also a pointer to pointer of 4 integers and not pointer to pointer of integers and hence not compatible.

    #include<stdio.h>
    void foo(float (*pm)[4])
    {
        int i,j;
        for (i = 0; i < 4; i++)
            for (j = 0; j < 4; j++)
                printf("%f\n", pm[i][j]);
    
    }
    
    int main ()
    {
        float m[4][4];
        int i,j;
        for (i = 0; i < 4; i++)
            for (j = 0; j < 4; j++)
                    m[i][j] = i+j;
    
        foo(m);
     }
    

0

使用支持运行时大小数组的C99,以下是传递二维数组的可能方法:

void foo(void *pm, int row, int col)
{
    float (*m)[col] = pm;

    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            printf("%4.1f%s", m[i][j], (j == col-1)?"\n":" ");

}

int main()
{
    float m[4][4];

    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            m[i][j] = i+j;

    foo(m, 4, 4);

    return 0;
}

0
typedef float Float4[4];

void foo(Float4 *pm)
{
  int i,j;
  for (i = 0; i < 4; i++)
    for (j = 0; j < 4; j++)
      printf("%f\n", pm[i][j]);
}

main()
{
  Float4 m[4];

  int i,j;
  for (i = 0; i < 4; i++)
    for (j = 0; j < 4; j++)
      m[i][j] = i+j;

  foo(m);
  return 0;
}

2
这怎么满足了要求:“我不被允许更改foo()的代码或原型?” - caf

0

foo(m) 不起作用吗?


哦,我已经很久没有真正使用C语言和指针了(也许有20年)。 - Frank

0

void foo(float **pm)就是void foo(float *pm[]),而不是一个二维数组的浮点数。它是一个float*类型的数组。现在,这些float*可能指向浮点数数组,但那是另一回事。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接