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

9 Answers 9

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Carl is also malloc -ing each row separately, whereas AndreyT's example leaves the actual data in a single block.
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!

5 Comments

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.
Sure, but it's not wrong - the solution to the problem is to change the type of m.
@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, that seems fair - I interpreted it as being unable to change foo() only.
@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.
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);

Comments

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)

Comments

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

Comments

0

Does foo(m) not work?

1 Comment

Oh, it is long time since I really used C and pointers (maybe 20 years).
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.

Comments

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

1 Comment

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.