Here's a version which is both working, but theoretically invalid (see below) C90 and C++98:
#include <stdio.h>
static void print(int *arr, size_t s1, size_t s2)
{
size_t i, j;
printf("\n");
for(i = 0; i < s1; i++) {
for(j = 0; j < s2; j++) {
printf("%d, ", arr[i * s2 + j]);
}
}
printf("\n");
}
int main(void) {
int a[4][4] = {{0}};
print(a[0], 4, 4);
return 0;
}
A C++ version using templates (adapted from Notinlist's answer) could look like this:
#include <iostream>
#include <cstring>
using namespace std;
template <size_t N, size_t M>
struct IntMatrix
{
int data[N][M];
IntMatrix() { memset(data, 0, sizeof data); }
};
template <size_t N, size_t M>
ostream& operator<<(ostream& out, const IntMatrix<N,M>& m)
{
out << "\n";
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
out << m.data[i][j] << ", ";
}
}
out << "\n";
return out;
}
int main()
{
IntMatrix<4,4> a;
cout << a;
return 0;
}
Alternatively, you could use nested STL containers - ie vector< vector<int> >
- instead of a plain array.
With C99, you could do
static void print(size_t s1, size_t s2, int arr[s1][s2]) {
printf("\n");
for(size_t i = 0; i < s1; i++) {
for(size_t j = 0; j < s2; j++) {
printf("%d, ", arr[i][j]);
}
}
printf("\n");
}
and call it as
print(4, 4, a);
As Robert pointed out in the comments, the first snippet actually involves undefined behaviour. However, assuming that pointer arithmetics will always result in a pointer even when undefined behaviour is involved (and not blow up your computer), there is only a single possible result because of other restrictions within the standard, ie this is an instance of where the standard leaves something unnecessarily undefined.
As far as I can tell, substituting
print(a[0], 4, 4);
with
union m2f { int multi[4][4]; int flat[16]; } *foo = (union m2f *)&a;
print(foo->flat, 4, 4);
will make it legal C.