La raison principale n'est pas la connaissance de la taille du tableau ou non. La raison principale est la duree de vie de la variable et la zone memoire ou elle est allouee:
int tab[size];
place le tableau dans la pile d'execution. D'abords, cette pile est limite en taille, typiquement quelques MB, ce qui implique que tu ne peux pas avoir de gros tableau. Mais aussi tu la tableau n'existe plus une fois que la fonction fini. Tu ne peux pas retourner ce tableau a la fonction appellante. Une fois que la fonction est termine, le tableau est retire de la pile.
Alors que quand le tableau est alloue
int* tab = malloc (size*sizeof(int));
le tableau est alloue dans le tas. Le tas n'a pas de limite memoire, il est seulement limite par la taille de la memoire de ta machine (c'est plus complique, mais faisons simple). Aussi le tas ne disparait pas quand tu quittes la fonction, donc ca te permet potentiellement de retourner a la fonction appellante le tableau qui a ete alloue.