0

In a given exercise in C programming language, there is a function that should return an array of arrays (out in the function foo signature) of "pairs" of integer variables [ [x1, y1], [x2, y2], .... ]

The prototype looks like this:

void foo(int*** out)
{
   ....
}
  1. What is the meaning of the argument format?
  2. Does the functions receives a pointer to the out array, or does it have to allocate the memory for the the array by itself?
Adam
  • 2,820
  • 1
  • 13
  • 33
Gaston
  • 3
  • 4
  • Its a pointer to pointer to pointer to int. – tkausl Jun 11 '20 at 13:54
  • probably, the function `foo` needs to generate (on the heap for sure) an array of pointers to int type and return it by derefrence the `out` parameter/function argument – Adam Jun 11 '20 at 13:57
  • visibly *foo* has to allocate your array and set the in-out variable *out* with its address, this is why your function is *void* rather than `int**` – bruno Jun 11 '20 at 13:57
  • Most likely your source of learning doesn't know how to [Correctly allocate multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). That post also deals with "three star programming" and other such confused anti-patterns. – Lundin Jun 11 '20 at 13:57
  • @Lundin: *Sometimes* multiple indirection is not the wrong answer. Not saying that's the case here, but it's not necessarily an anti-pattern. – John Bode Jun 11 '20 at 15:07
  • @JohnBode In the rare case where you need to return a `type**` through parameters, then yeah there is a valid use-case for `type***`. But most often the need for more than 2 levels of indirection is a sign of bad program design. – Lundin Jun 12 '20 at 06:39

1 Answers1

3

Based on the description, the most likely interpretation is that you are passing a pointer to an int ** object, and foo allocates memory for that object, so you'd have

void foo( int ***out )
{
  *out = ...; // omitting actual allocation here since it's homework,
              // but I can guarantee it won't be a single statement
}

int main( void )
{
  int **pairs;
  ...
  foo( &pairs ); 
  ...
}

Note than an object of T ** is not a 2-dimensional array; it can be used to implement something that can be indexed like a 2D array, but the "rows" don't have to be contiguous or even the same length. It basically looks something like this:

pairs       pairs[i]        pairs[i][0], pairs[i][1]
int **      int *           int
+---+       +---+           +---+---+
| +-+-----> | +-+---------> |   |   |
+---+       +---+           +---+---+
            | +-+------+
            +---+      |    +---+---+
            | +-+---+  +--> |   |   |
            +---+   |       +---+---+
             ...    |     
                    |       +---+---+
                    +-----> |   |   |
                            +---+---+

IOW, you have an object pairs that points to a sequence of int *, each of which (pairs[i]) points to a sequence of int. Because of how the [] subscript operator works, you can index into this structure using 2D array notation (pairs[i][j]), but otherwise it doesn't look or act like a 2D array.

So I'm assuming the job of foo is to allocate the memory for a structure like that, where each pairs[i] points to a sequence of 2 int. Since it needs to write a new value to pairs, we need to pass a pointer to pairs. Since pairs has type int **, that means the expression &pairs has type int ***.

I can tell you this will be a multi-step process - you will need to make multiple calls to malloc or calloc. The diagram above should give you some hints on how to do that.

John Bode
  • 119,563
  • 19
  • 122
  • 198