si no entiendes bien el tema apuntadores repasalos en este enlace que no es muy largo y esta bien explicado:
http://c.conclase.net/curso/?cap=012en cuanto a las matrices, estas no son mas que un apuntador a un array de apuntadores a entero (en este caso). en el code que te deje tendriamos esto:
i j
matriz -> | a | -> | 1 | 2 | 3 |
| b | -> | 4 | 5 | 6 |
| c | -> | 7 | 8 | 9 |
donde los vectores 123, 456, 789 son un array de enteros, y representan las filas de la matriz. el vector abc es un array de apuntadores a enteros: "a" es un apuntador a entero (int*) y apunta a "1"; "b" es un apuntador a entero y apunta a "4"; etc. y luego "matriz" es un apuntador a un array de apuntadores (int**), y "matriz" apunta, como en toda cadena de cualquier cosa, al primer elemento "a".
entonces, si por ejemplo quieres acceder al numero 4, y cogemos los indices i,j del dibujo, seria: matriz[1][0] (recuerda que los arrays empiezan en la posicion 0), o lo que es lo mismo: *(*(matriz+1)+0). para el numero 8 seria matriz[2][1] o *(*(matriz+2)+1). etc.
si hasta aqui lo entiendes, entonces lo de pasar por referencia a una funcion como parametro no es mas que darle el apuntador de la matriz a la funcion, en este caso "matriz". asi luego dentro de la funcion podras acceder y modificar cualquier elemento de la matriz.
no se si me explique muy bien, ahora comentare un poco el code de antes y si tienes alguna duda en particular intentaremos resolverla.
un saludo!
edito:
No es valida si se compila según el estándar C90, este requiere que el numero de elementos en un array se indique mediante una expresión constante.
Pero en los dos siguientes estándares de C (C99 y C11) si es posible, a esos arrays donde el numero de elementos se calcula en tiempo de ejecución se les conoce como "variable length arrays" o "VLAs".
gracias por comentarlo, no tenia ni idea y ya me he puesto al dia leyendo sobre ello.