where
f1a and f1b accept conventional two-dimensional arrays,
f2 accepts a ``flattened'' two-dimensional array,
and
f3 accepts a pointer-to-pointer, simulated array
(see also questions
6.18
and
6.19),
the following calls
should
work as expected:

It will be noticed that only f2 can conveniently be made to work
with both statically- and dynamically-allocated arrays,
though
it will
not
work with the traditional
``ragged'' array implementation,
array1.
However,
it must also
be noted that
passing &array[0][0]
(or, equivalently, *array)
to f2
is not strictly conforming;
see question
6.19.

If you can understand why all of the above calls work and are
written as they are,
and if you understand why the combinations that are not listed
would not work,
then you have a
very
good understanding of arrays and pointers
in C.

Rather than worrying about all of this,
one approach to using multidimensional arrays of various sizes
is to make them all dynamic,
as in question 6.16.
If there are no static multidimensional arrays--if
all arrays are allocated like array1 or array2
in question 6.16--then
all functions can be written like f3.