Originariamente inviato da programfile
Quindi:
Sapendo che a livello teorico quello che ho scritto con gli asterischi è un errore, mi preme sapere perchè viene compilato cmq il codice.
E' il programma che uso che ha dei limiti e permette questi erroracci, oppure c'è qualcosa sotto, tipo che si può fare una cosa del genere in C++?
Lo standard C++ dice che sforare da un array è "undefined behavior"; questo significa che potrebbe funzionare tutto, potrebbe andare in crash il programma o potrebbero atterrare gli alieni e deportarci tutti su alpha centauri.

Nel mondo reale, la questione è la seguente: quando specifichi le dimensioni di un array, stai semplicemente dicendo al compilatore quanto spazio riservare per l'array in questione. Al momento di accedere agli elementi non è effettuato alcun controllo sull'indice inserito, fondamentalmente per ragioni di efficienza (lo standard dice che l'accesso ad un array come array[indice] deve essere equivalente all'espressione *(array+indice), che, essendo una semplice somma di puntatori, non prevede controlli di alcun genere).

Questo significa che, andando oltre le dimensioni dell'array, nessuno ti dice niente, ma stai andando a scrivere in memoria che non è quella riservata all'array. Se sei fortunato il programma va in crash subito (questo accade in particolare se l'area immediatamente successiva al tuo array è memoria protetta, cosa praticamente impossibile per le variabili locali), altrimenti vai a sovrascrivere altre variabili (in genere situate nella procedura corrente per le variabili locali), in cui probabilmente ti ritroverai valori "strani".

Altrimenti, potresti andare a sovrascrivere l'indirizzo di ritorno della procedura corrente, per cui, al momento di ritornare, la procedura corrente cercherà di tornare ad un indirizzo che non c'entra un tubo, causando il crash del programma o (peggio) l'esecuzione di codice che non c'entra niente.

In ogni caso, tutto questo è male. Stai sempre attento a non sforare dagli array, molti bachi di sicurezza derivano da problemi di questo genere.
2° domandina:
Da quello che so un array deve essere sempre definito con una costante. Anche se sia variabile (come nell'esempio sopra), si imposta a costante.
Perchè allora se compilo un programma con dimensione di array solamente definita come:
int dim;
int array[dim]

senza porre come costante la variabile dim, il programma mi si compila ed esegue lo stesso?
A mia vista si esegue correttamente. Perchè?
Sempre errore del compilatore?
Oppure è possibile che un array sia definito come ho scritto qualche riga sopra (cioè con variabile non costante)?
È un'estensione non-standard del compilatore gcc. Nel C99 gli array allocati sullo stack ma a dimensione variabile (VLA) sono stati standardizzati, mentre nel C++ non sono stati accettati per diverse ragioni. In linea di massima in C++ se serve un array le cui dimensioni sono note solo a runtime si usa l'heap (con gli operatori new e delete).