Oi William,
Não sei se é um pouco tarde, mas seguem as respostas:
1) Como ela foi declarada dentro da função, ela só "existe" enquanto você está na função, e ela é destruída assim que você sai dela.
2) Se você a declarou fora da função, e só a alocou lá dentro, isso funciona pois o espaço de memória para a matriz não é perdido após sair da função, como no primeiro caso. Além disso, como matrizes são tratadas como ponteiros, mudanças feitas sobre eles mesmo dentro de outras funções são percebidas mesmo quando retornamos da função.
3) Isso tem a ver com o que chamamos de passagem por valor ou passagem por referência. Quando passamos um ponteiro (como uma matriz), estamos passando uma referência (endereço de memória) para a variável. Neste caso, mudanças realizadas lá são percebidas por todos, já que todos estarão acessando o mesmo endereço de memória que foi alterada. No caso de outras variáveis simples (int, float, struct sem ponteiros, etc.), as passagens são feitas por valor, ou seja, não estamos passando apenas o valor da variável, não ela propriamente dita. Em outras palavras, passamos uma cópia de seu valor. Assim, mudanças feitas sobre esses valores são perdidos, já que são apenas cópias.
Espero ter ajudado.
Henrique