1)
выделяется только память под массив указателей на массивы(одномерный, "список строк").
надо ещё под второе измерение память выделить в цикле на каждый указатель(сами "строки") и заполнить первый массив указателями на них
и только тогда
"*(*(matr+i)+j)"
даст этот элемент
разбор конструкции:
"matr" - указатель на массив `указателей на строки`(он же указатель на 0-й элемент массива указателей на строки, те указатель на `указатель на 0-й массив-строку`)
"matr+i" -- указатель на `указатель на i-й массив-строку`
"*(matr+i)" -- указатель на i массив-строку(он же "matr[ i]"). если память под строку не выделена, то указывает в NULL или в мусор
"(*(matr+i))+j "-- указатель на j-й элемент i-го массива-строки(он же "(matr[ i])+j")
"*( (*(matr+i)) +j )" -- j-й элемент i-го массива-строки(он же "matr[ i][ j]")
2)
тут сразу выделяется память единым непрерывным куском в одномерном массиве
и обращаться к элементу надо не двумерно, а одномерно вычисляя его положение
"*(matr+i*n+j)"
или
"matr[ i*n+j]"