klose87 ha scritto:Si parla di C, ma i 2 schieramenti contrapposti sono un classico che dura nel tempo: veterani vs. apprendisti.

Mi sono appassionato alla discussione perché appartengo ad una terza categoria: quella dei dilettanti allo sbaraglio. Mi sono avvicinato seriamente al C da appena un mese (causa università), devo dire che mi sta veramente intrigando.
Non prendetela come una provocazione, è una domanda seria che mi è venuta leggendo qui: se riservo 7 zone di memoria, ci sono dei casi pratici in cui ho benefici nel controllare l'ottava? Mi rendo conto che potrebbe essere una domanda priva di senso e/o inutile, in tal caso fatemelo notare...
Diciamo che dipende da come stai gestendo la memoria.
Se in tutto l'applicativo inizializzi solo quelle 7 ipotetiche zone di memoria, non le riallochi mai etc etc, allora la risposta è no, chiaramente no.
Il fatto è che questo il compilatore non lo può sapere, perchè l'inizializzazione della memoria ed il suo utilizzo dipendono dal codice eseguito in runtime, codice che può essere estremamente articolato e complesso, variare in base all'input dell'utente, allo stato delle periferiche, etc etc etc. Non è possibile *simulare* ogni pattern in fase di compilazione di un programma, è semplicemente irrealizzabile. Realizzarla parziale giusto per avere un warning sarebbe, IMHO, una drammatica perdita di tempo poichè coprirebbe un caso su... un triliardo? E soprattutto fornirebbe la scusa per non scrivere/usare codice necessario a gestire gli errori
quando invece è obbligatorio farlo.
Es.: Supponi del codice di questo tipo:
Codice: Seleziona tutto
#include "stdio.h"
int
main (void)
{
int giorni[30] = {0};
int i = 0;
for (i = 0; i < 31; i++)
{
if (i % 2 == 1)
{
printf("%d ", i);
giorni[i] = 1;
}
}
printf("\ndone.\n");
return 0;
}
"giorni" è composto da 30 elementi, numerati da 0 a 29.
Il ciclo for prosegue da 0 a 30, per cui ipoteticamente "giorni[ i ] = 1" potrebbe causare un errore di violazione della memoria.
In realtà questo non accadrà mai perchè if (i % 2 == 1) gli farà considerare solo gli elementi dispari, per cui l'ultimo ad essere processato è il 29.
Output:
Codice: Seleziona tutto
samuele@nuitari-laptop:~$ gcc check4.c && a.out
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29
done.
Domanda: come potrebbe mai un compilatore capire una cosa del genere??? Risposta: non può. E qui è semplice... potrebbe essere MOLTO più complesso di così.
L'unico tipo di controllo sulla memoria è quello fornito dal kernel, ma è un discorso di natura diversa e comunque avvisa solo che c'è stata una violazione e da eventualmente le informazioni utili a debuggare, ma di certo non comunica in quale riga del listato originale è avvenuto l'errore.
Il punto è che quando si lavora con la memoria in modo diretto, senza passare da funzioni d'interfaccia studiate ad hoc (come ad esempio una classe per la gestione di vettori), è tutto in mano al programmatore.
Il C mette a disposizione solo operazioni con i puntatori, che siano espliciti definendo variabili di tipo puntatore od impliciti utilizzando operatori unari come "*" o "&" o binari come le parentesi []. Per gestire strutture di dati complesse, come ad esempio gli array, è necessario scrivere del codice ad hoc SE si desidera che il programma non termini con un errore non gestito, dato che comunque errare humanum est.
La stessa inizializzazione di un gruppo di variabili con le parentesi [] è limitante. Ad esempio la dimensione non è ridefinibile in runtime, cosa che invece può accadere con malloc. Il motivo è, ancora una volta, che le parentesi [] non sono state pensate per la gestione dell'"oggetto array", un concetto di ben più alto livello.
@Mario Vanoni:

Nessuno finisce mai d'imparare, io per primo =)