C99-style MD-arrays

This is not only a very ugly peice of software code, but also a very bad one (and I'm not talking about the missing error checks, let's just ignore them):

int ***mdarr = (int ***)malloc(n1 * sizeof(**int));
for (size_t i = 0; i < n1; i++) {
  mdarr[i] = (int **)malloc(n2 * sizeof(*int));
  for (size_t j = 0; j < n2; j++) {
    mdarr[i][j] = (int *)malloc(n3 * sizeof(int));
    for (size_t k = 0; k < n3; k++)
      mdarr[i][j][k] = get_data(i, j, k);
  }
}

Obviously this was written by a C++-programmer. Let's clean it up a bit: we don't need to cast void-pointers in C.

int ***mdarr = malloc(n1 * sizeof(**int));
for (size_t i = 0; i < n1; i++) {
  mdarr[i] = malloc(n2 * sizeof(*int));
  for (size_t j = 0; j < n2; j++) {
    mdarr[i][j] = malloc(n3 * sizeof(int));
    for (size_t k = 0; k < n3; k++)
      mdarr[i][j][k] = get_data(i, j, k);
  }
}

Much better, but still, we want one allocation of contiguous virtually memory.

int *mdarr = malloc(n1 * n2 * n3 * sizeof(int));
for (size_t i = 0; i < n1; i++)
  for (size_t j = 0; j < n2; j++)
    for (size_t k = 0; k < n3; k++)
      mdarr[i*n2*n3 + j*n3 + k] = get_data(i, j, k);

Very nice. But we can do better still. Using macros, we can removing the addressing logic, but we have C99, so we will not go that route.

int (*mdarr)[n1][n2][n3] = malloc(sizeof(*mdarr));
for (size_t i = 0; i < n1; i++)
  for (size_t j = 0; j < n2; j++)
    for (size_t k = 0; k < n3; k++)
      (*mdarr)[i][j][k] = get_data(i, j, k);

Perfect, but if you know that it fits on the stack (you probably don't know that), you can (depending on the context) use C99's variable array-size feature:

int mdarr[n1][n2][n3];
for (size_t i = 0; i < n1; i++)
  for (size_t j = 0; j < n2; j++)
    for (size_t k = 0; k < n3; k++)
      mdarr[i][j][k] = get_data(i, j, k);