На эту тему есть хорошее высказывание: "В языке С нет многомерных массивов, но есть массивы из одномерных массивов".

Ваша задача традиционно решается иным заданием исходного массива:
Код
// создаем массив массивов NxM:
int i;
float **matrix;
matrix = (float**)malloc( N * sizeof(float*)); // создаем массив указателей на строки
for( i=0; i < N; i++) matrix[i] = (float*)malloc( M * sizeof(float)); // аллокируем строки
// зовем функцию:
func( matrix, N, M); // заполняет матрицу NxM единичками
// удаляем массив:
for( i=0; i < N; i++) free( matrix[i]); // удаляем строки
free( matrix); // удаляем указатель на них
.....
// сама функция определена так:
void func( float **matrix, int N, int M)
{
int i, j;
for( i=0; i < N; i++)
for( j=0; j < M; j++)
matrix[i][j] = 1; // заполняем единичками
}
Заметим, что, несмотря на "вычурность" инициализации такой матрицы, она поддерживает традиционное обращение к своему элементу - matrix[i][j].
Кстати, этот случай как раз хорош для C++, т.к. в нем удобно создать класс для квадратных матриц, где их создание запихнуть в конструктор, а удаление в деструктор.