I wonder If there's a way to assign a dynamic array (in c), values like in the case of a non dynamic array (instead of matrix[0][0] = ...)
For 2D arrays, only on declaration, e.g.:
int matrix[][3] = {{1,1,1},{2,0,2},{3,3,3}};
Or
int matrix[][3]{{1, 1, 1}, {2, 0, 2}, {3, 3, 3}};
Value initialization of arrays is allowed.
After that you can't, matrix is not a modifiable lvalue, you can't directly assing values in such fashion.
Later adding values is exactly the same in both situations, using matrix[0][0] = ..., this is valid for both 2D arrays and for pointer to pointer allocations, it's a fine substitute for pointer dereference notation I might add.
And how would I pass the non dynamic array int matrix[3][3] =  {{1,1,1},{2,0,2},{3,3,3}}; to a function like void printmatrix(int **matrix, int n)?
It can't be done, one is a pointer to pointer to int, the other is an array of arrays of ints, aka a 2D array of int's, these are incompatible, you cannot pass any one of them to an argument of the other.
At most you can pass an array of pointers, i.e. int* matrix[SIZE] can be passed to an argument of type int **matrix, and this is because the array will decay to a pointer when passed as an argument.