Reconstructing Matrix scattered over many MPI ranks
Note: I've written a matrix multiplication benchmark program in C and MPI:https://github.com/thefangbear/matrix-mpi. It uses a row-major format to store the two matrices in 1D arrays for better cache coherency. It also supports both synchronous and asynchronous send/receive modes, tunable via a preprocessor macro, so you can take a look.

With that being said, let's turn to a few improvable parts in your code: 


You don't have to use an array of pointers to represent the matrix format. You can use an 1D array with row-major/column-major format. If you use a "2D array" (array of pointers), each row/colum slice of your matrix are not guaranteed to be stored in consecutive locations.
Isend/Irecv lead to degraded performance. You can verify this via benchmarking. MPI sends/receives extra messages when asynchronous mode is used, which makes basic operations more expensive. And since you have blocking anyways somewhere in your code, ISend/IRecv do not make a huge difference.
It is common for worker nodes to send back processed slices of data to be merged and outputted in the master node. You can technically just invoke printf in a loop on each worker node to output its own slice of data (since mpirun redirects all stdout streams on each node to your terminal screen), but MPI does not guarantee the order of output.
If you want a more elegant semantics, you should checkout MPI_Scatterv/MPI_Gatherv scatter/gather functions: https://www.mpich.org/static/docs/v3.1/www3/MPI_Scatterv.html. (But I don't think you'll get significant performance gains by using them)