#include <stdio.h>
#include <stdlib.h>

int** My2DAlloc(int nrows, int ncols) {
  int** array = malloc(nrows * sizeof(int*)); 
  for(int k = 0; k < nrows; k++){
    array[k] = malloc(ncols * sizeof(int));
  }
  return array;
}

int** My2DAllocOneMalloc(int nrows, int ncols) {
  int header_size = nrows * sizeof(int*);
  int data_size = nrows * ncols * sizeof(int);
  int** array = (int**) malloc(header_size + data_size); 
  int* data_start = (int*) (array + nrows);
  for(int k = 0; k < nrows; k++) {
    array[k] = data_start + k*ncols; 
  }
  return array;
}

void test2DArray(int** array, int nrows, int ncols) {
  // Populate it with values
  for (int i = 0; i < nrows; i++) {
    for (int j = 0; j < ncols; j++) {
      array[i][j] = i + j + 1;
    }
  }
  // Print out values
  for (int i = 0; i < nrows; i++) {
    for (int j = 0; j < ncols; j++) {
      printf("%d\t", array[i][j]);
    }
    printf("\n");
  }
}

int main() {
  int nrows = 4;
  int ncols = 6;
  
  int** A = My2DAlloc(nrows, ncols);
  test2DArray(A, nrows, ncols);

  // Clean up A
  for (int i = 0; i < nrows; i++) {
    free(A[i]);
  }
  free(A);

  int** B = My2DAllocOneMalloc(nrows, ncols);
  test2DArray(B, nrows, ncols);

  // Clean up B
  free(B);
}