10

How do I pass the m matrix to foo()? if I am not allowed to change the code or the prototype of 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???);
}
user424346
  • 101
  • 1
  • 1
  • 3

9 Answers9

15

If you insist on the above declaration of foo, i.e.

void foo(float **pm)

and on using a built-in 2D array, i.e.

float m[4][4];

then the only way to make your foo work with m is to create an extra "row index" array and pass it instead of m

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

There no way to pass m to foo directly. It is impossible. The parameter type float ** is hopelessly incompatible with the argument type float [4][4].

Also, since C99 the above can be expressed in a more compact fashion as

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

P.S. If you look carefully, you'll that this is basically the same thing as what Carl Norum suggested in his answer. Except that Carl is malloc-ing the array memory, which is not absolutely necessary.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Carl is also `malloc` -ing each row separately, whereas AndreyT's example leaves the actual data in a single block. – caf Aug 18 '10 at 23:37
8

If you can't change foo(), you will need to change m. Declare it as float **m, and allocate the memory appropriately. Then call foo(). Something like:

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

Don't forget to free() afterwards!

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • The technique that you use has no relation to dynamic allocation of memory whatsoever. Since the array sizes are constant, you can just as well allocate the memory "on the stack", just like it was in the OP. – AnT stands with Russia Aug 18 '10 at 18:00
  • Sure, but it's not wrong - the solution to the problem is to change the type of m. – Carl Norum Aug 18 '10 at 18:10
  • @Carl Norum: Not necessarily. The problem, as stated, seems to imply that the existing `foo` must be made to work with the existing `m`. And the solution to the problem is to change the type of what is passed to `foo`, not the type of `m`. – AnT stands with Russia Aug 18 '10 at 18:13
  • @AndreyT, that seems fair - I interpreted it as being unable to change `foo()` only. – Carl Norum Aug 18 '10 at 18:18
  • @Carl Norum: You are right. That's probably what was implied by the OP. I'm just saying that switching to dynamic allocation is not really absolutely required. – AnT stands with Russia Aug 18 '10 at 18:34
3

You can't. m is not compatible with the argument to foo. You'd have to use a temporary array of pointers.

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);
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
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);
     }
    
abhay jain
  • 146
  • 1
  • 8
2

If you have a compiler that supports C99, the current C standard, then you can do this:

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

(Note that this is exactly the same as AndreyT's answer, except that it forgoes having to name the temporary array)

Community
  • 1
  • 1
caf
  • 233,326
  • 40
  • 323
  • 462
0

Does foo(m) not work?

Frank
  • 2,628
  • 15
  • 14
0

void foo(float **pm) is the same as void foo(float *pm[]) which is not a two-dimensional array of floats. It is an array of float*. Now, those float* may themselves point to float arrays, but that's a separate matter.

James Curran
  • 101,701
  • 37
  • 181
  • 258
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;
}
user411313
  • 3,930
  • 19
  • 16
  • 2
    How does this satisfy the requirement *"I am not allowed to change the code or the prototype of foo()?"* ? – caf Aug 18 '10 at 23:41
0

Using C99 which supports run-time sized arrays, the following is a possible way to pass a 2-dim array:

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;
}
Simon Woo
  • 474
  • 3
  • 5