C pointer to one integer
  int* pt = (int*)malloc(sizeof(int));
  pt[0] = 3;
  printf("%d", pt[0]);

  // free memory
  free(pt);
  
C pointer to array of integer
  int num = 4;
  int* pt = (int*)malloc(sizeof(int) * num);
  for(int i = 0; i < num; i++){
       pt[i] = i;
  }
  for(int i = 0; i < num; i++){
       printf("%d\n", pt[i]);
  }
  // free memory
  free(pt);
  
There is no difference between free pointer to ONE Int or array of Int with ONE Int is same as ONE element of array of Int
C allocate 2d array and free them.
  int height = 3;
  int width = 4;
  // allocate memory for height x width 2d array.
  int** pt2 = (int**)malloc(sizeof(int*)*height);
  for(int i=0; i< height; i++){
      pt2[i] = (int*)malloc(sizeof(int)*width);
  }

  for(int i = 0; i < height; i++){
      for(int j = 0; j < width; j++){
          pt2[i][j] = i + j;
      }
  }


  // deallocate the memory
  for(int i=0; i< height; i++){
      free(pt2[i]);
  }
  if(pt2 != NULL)
      free(pt2);
  
Copy int** arr to int** duplicated_arr

int** arr ⇒ int** duplicated_arr int** arr int** duplicated_arr +-+ +-+ | | → int ← - -+ | | | | | | | | | → int | | | | | ↑ | | | +-+ | | +-+ | | +-+ | | - → | | → int | | | + - - - - - → | | → int | | +-+ free int** arr ⇒ 🗑 +-+ | | | | | | | | +-+ Copy int** to other int** 0. Given an original int** arr 1. We want to copy int** arr to int** duplicated_arr 2. We can allocate int** duplicated_arr first 3. Copy all int* from int** arr to int** duplicated_arr 3. free int** arr
  int num = 3;
  int** arr = (int**)malloc(sizeof(int*) * num);
  int** duplicated_arr = (int**)malloc(sizeof(int*) * num);

  for(int i = 0; i < num; i++){
    arr[i] = (int*)malloc(sizeof(int));
    arr[i][0] = i;
  }

  for(int i = 0; i < num; i++){
    pl("arr[%d][0]=%d", i, arr[i][0]);
  }

  // copy int** arr  => int** duplicated_arr
  for(int i = 0; i < num; i++){
    duplicated_arr[i] = arr[i];
  }

  free(arr);

  for(int i = 0; i < num; i++){
    pl("duplicated_arr[%d][0]=%d", i, duplicated_arr[i][0]);
  }

  for(int i = 0; i < num; i++){
    free(duplicated_arr[i]);
  }
  
Reallocate memory with old pointer or extend old pointer memory
  1. Use realloc(oldpt, sizeof(int)*len); 
  
  #include <cstdlib>
  void* realloc(void* ptr, size_t size); 
  
  +--------+     +----------+ +--+
  |        | ->  |          | |  |
  +--------+     +----------+ +--+
  int len = 4;     
       ↑ 
       + ----->  2*len

  float* arr = (float*)malloc(sizeof(float)*len);

  for(int i = 0; i < len; i++){
      arr[i] = i;
  }

  printArrayX(arr, len);

  arr = (float*) realloc(arr, sizeof(float)*(2*len));
   ↑                      ↑
   + →  Reuse pt          + → Append len float to arr


  for(int i = len - 1; i < 2*len; i++){
     arr[i] = (10*i);                      
  }

  fw("2*len");
  printArrayX(arr, 2*len);

  free(arr);

  
Cpp new and delete in 2D
  // two dimension array
  int ncol = 4, nrow = 3;
  int** arr = (int**) new int*[ncol];    
  // allocate row
  for(int j=0; j < 2; j++){
      arr[j] = (int*) new int[nrow];
  }
  //
  for(int j=0; j < ncol; j++){
      arr[j] = (int*) new int[nrow];
      for(int i = 0; i < nrow; i++){
          arr[j][i] = j * ncol + i; 
      }
  }

  printArray2dint(ncol, nrow, arr);

  for(int i=0; i < ncol; i++) 
      delete[] arr[i];
  delete[] arr;
  
3D array, 3d cube
    printf("2 x 3 x 4 cube\n");

    /*
             \
              \
                 - - - - >
               /
              /
             /
    */

    int arr[2][3][4];
    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 3; j++) {
            for(int k = 0; k < 4; k++) {
                arr[i][j][k] = i + j + k;
            }
        }
    }

    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 3; j++) {
            for(int k = 0; k < 4; k++) {
                printf("%d ", arr[i][j][k]);
            }
            printf("\n");
        }
        printf("\n");
    }

    /*
    2 x 3 x 4 cube

    0 1 2 3
    1 2 3 4
    2 3 4 5

    1 2 3 4
    2 3 4 5
    3 4 5 6
    */
  
Compare C++ allocate 3D array and C malloc 3D array
    int* a1 = (int*) new int;
                          ↑
                          ⇳
                          ↓
    int* a1 = (int*) new int[1]
                          ↑
                          + -> 1 □ contains ℕ

    int** a2 = (int**) new int*[10];
                             ↑
                             + -> 10 □ contains ℕ*

    int*** a3 = (int***) new int**[10];
                                ↑
                                + -> 10 □ contains ℕ**


    int* a1 = (int*) malloc(sizeof(int));
                                    ↑
                                    ⇳
                                    ↓
    int* a1 = (int*) malloc(sizeof(int) * 1);
                                          ↑
                                          + -> 1 □ contains ℕ

    int** a2 = (int**) malloc(sizeof(int*) * 10);
                                              ↑
                                              + -> 10 □ contains ℕ*
                   
    int*** a3 = (int**) malloc(sizeof(int**) * 10);
                                                ↑
                                                + -> 10 □ contains ℕ**
                   
  
Allocate and Deallocate functions in C++
  int* allocate(int size){
          return new int[size];
  }

  void deallocate(int*& pt){
          delete[] pt;
              pt = NULL;
  }
  
Why You can NOT find the length of array if you allocate memory dynamically
  int* arr = new int[10];
  int len = sizeof(arr)/sizeof(int); // not equal 10

  int arr[10];
  int len = sizeof(arr)/sizeof(int); // => equal 10

  
Dynamically allocate two dimension array in C
  int height = 3;
  int width  = 4;
  int* pt = (int*)malloc(sizeof(int)*width);

  int** array = (int**)malloc(sizeof(int*)*height);
  for(int i = 0; i < height; i++)
      array[i] = (int*)malloc(sizeof(int)*width);
  


Allocate and Deallocate 3D array or tripple pointers in C/C++/ObjectiveC with malloc