tags:

views:

106

answers:

7

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???);
}
+3  A: 

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
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.
AndreyT
Sure, but it's not wrong - the solution to the problem is to change the type of m.
Carl Norum
@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`.
AndreyT
@AndreyT, that seems fair - I interpreted it as being unable to change `foo()` only.
Carl Norum
@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.
AndreyT
@AndreyT, no argument there.
Carl Norum
A: 

Does foo(m) not work?

Frank
No, it doesn't. A 2D array is not a pointer to a pointer.
Justin Ardini
Oh, it is long time since I really used C and pointers (maybe 20 years).
Frank
+5  A: 

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].

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.

AndreyT
Carl is also `malloc` -ing each row separately, whereas AndreyT's example leaves the actual data in a single block.
caf
+2  A: 

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);
Charles Bailey
A: 

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
+1  A: 
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;
}
How does this satisfy the requirement *"I am not allowed to change the code or the prototype of foo()?"* ?
caf
A: 

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)

caf