【问题标题】:Passing two-dimensional array via pointer通过指针传递二维数组
【发布时间】:2010-08-18 17:52:05
【问题描述】:

如何将 m 矩阵传递给 foo()?如果我不允许更改 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???);
}

【问题讨论】:

    标签: c arrays pointers


    【解决方案1】:

    如果你坚持上述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-ing 数组内存,这不是绝对必要的。

    【讨论】:

    • Carl 也是 malloc - 分别处理每一行,而 AndreyT 的示例将实际数据留在单个块中。
    【解决方案2】:

    如果您无法更改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 中一样在“堆栈上”分配内存。
    • 可以,但是没有错——解决问题的方法是改变m的类型。
    • @Carl Norum:不一定。如前所述,该问题似乎暗示必须使现有的foo 与现有的m 一起使用。而解决问题的方法是改变传递给foo的类型,而不是m的类型。
    • @AndreyT,这似乎很公平 - 我将其解释为无法仅更改 foo()。
    • @Carl Norum:你是对的。这可能是OP所暗示的。我只是说切换到动态分配并不是绝对必要的。
    【解决方案3】:

    你不能。 m 与 foo 的参数不兼容。你必须使用一个临时的指针数组。

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

    【讨论】:

      【解决方案4】:

      如果您的编译器支持当前的 C 标准 C99,那么您可以这样做:

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

      (请注意,这与AndreyT 的答案完全相同,只是它不必为临时数组命名)

      【讨论】:

        【解决方案5】:
        • 你不需要在 main 中做任何改变,但是如果你将函数的正式原型更改为 (*pm)[4] 或 pm[][4],你的函数将正常工作,因为 **pm 表示指针指向整数的指针,而 (*pm)[4] 或 pm[][4] 表示指向 4 个整数的指针。

          这里的m也是一个指向4个整数指针的指针,而不是指向整数指针的指针,因此不兼容。

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

        【讨论】:

          【解决方案6】:

          foo(m) 不工作吗?

          【讨论】:

          • 哦,我已经很久没有真正使用过 C 和指针了(可能是 20 年)。
          【解决方案7】:

          void foo(float **pm) 与void foo(float *pm[]) 相同,后者不是 一个二维浮点数组。它是float* 的数组。现在,那些float* 本身可能指向浮点数组,但这是另一回事。

          【讨论】:

            【解决方案8】:
            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;
            }
            

            【讨论】:

            • 这如何满足要求“我不允许更改foo()的代码或原型?” ?
            【解决方案9】:

            使用支持运行时大小数组的 C99,以下是传递 2-dim 数组的可能方式:

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

            【讨论】:

              猜你喜欢
              • 2020-12-16
              • 2014-07-29
              • 2013-05-19
              • 1970-01-01
              • 1970-01-01
              • 2021-10-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多