Newsgroup: it.comp.lang.c++
Titolo: Vettori "sfondati"

Ciao a tutti.
Facendo un test ho trovato una domanda:
" Dato il seguente spezzone di codice:
int B[10];
int i=9;
B[++i]=7;
a) Assegna a B[10] il valore 7.
b) Il compilatore dŕ errore.
Io ho risposto a. Il professore mi ha detto che quella giusta era b, poichč
dichiarando B[10] le posizioni di B vanno da 0 a 9 ( e questo lo sapevo
anche io) e quindi B[++i] che č uguale a B[10] non esiste.
Io ho provato a col Dev-C++ a scrivere il codice e a farmi restituire B[10]:
NESSUN ERRORE.
Qual č la spiegazione a tutto ciň?
Grazie

 b) Il compilatore dà errore.

 DEV-C++ fa schifo...
Non centra una mazza questo...
PS: Quota bene!
-- 
Luc.

 Grazie
un compilatore (C o C++ che compila un codice C)
non e' tenuto a verificare per te gli sfondamenti degli array.
percio' quel codice compila con successo.
il programma invece, una volta eseguito,
puo' comportarsi in qualsiasi modo:
-correttamente
-dare seg fault
-correttamente per un milione di volte e segfault
    alla un milione di volte piu' uno
- qualunque mix a piacere...
io arrivo fin qui.
qualcun altro magari ti potra' erudire
su classi array della libreria standard del c++ che
(forse, penso io) hanno un controllo sui bounds.

Quindi lasciando perdere il fatto in sè, la risposta giusta era quella che
ho dato io, quindi.
Anche io ho pensato come te, cioè che non è il compilatore che dà errore, in
quanto sintatticamente esatto, è la sementica che è sbagliata.
Che ne dici?


 Vincenzo
Questo non lo posso accettare... Come stanno le cose ora non lo so, ma ho
programmato con alcuni tra i più grandi compilatori C di tutti i tempi
(Lattice e Aztec, per esempio), che hanno fatto la storia dell'informatica
per più di venti anni (anche se adesso c'è il C++) e nessuno avrebbe
segnalato un errore di compilazione in quel caso.
Anzi c'era da diventare matti con i debugger per andare a vedere i nostri
programmi dove finivano per scrivere...
Anche la sua esecuzione non sempre avrebbe fallito, è semplicemente un
errore logico, che avrebbe provocato comunque risultati imprevedibili, quasi
sempre con la sovrascrittura di altri dati oppure un crash dell'applicazione
(una volta, quando i S.O. non erano protetti come quelli di oggi, capitava
di dover riavviare tutto...)
Uno dei vantaggi del C (ora sul C++ correggetemi voi che siete più bravi del
vecchio smanettone che vi scrive, anche se non ho ancora i capelli
bianchi...sto cominciando adesso... ahìme) era la possibilità di scrivere
codice veloce e snello proprio perché era in realtà un linguaggio di livello
"intermedio" e non "alto" come lo sono altri linguaggi.
Con il C si scrivono anche i sistemi operativi (e a maggior ragione si
potrebbe farlo con il C++, presumo, date le sue fantastiche
caratteristiche), quindi non c'è bisogno di appesantire il codice
controllando errori logici che un buon programmatore non dovrebbe compiere,
anche se oggi i microprocessori vanno sparati non hanno più nulla in comune
con i 6502 e gli z-80 di una volta, o con i seppur avvenieristici 68000 di
quei tempi lontani.
Scusate la breve parentesi nostalgica, ma non credo che la bontà di un
compilatore C/C++ si possa valutare da questo.
Paolo Ferraresi.

anche io) e quindi B[++i] che è uguale a B[10] non esiste.
O si' che esiste.
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

 Che ne dici?
Io avrei detto che in quel caso si ha un undefined behaviour.
Quindi, tecnicamente, nessuna delle due risposte sarebbe
corretta... Sbaglio?
--
Gerolamo

Ho capito.
Vado dal Prof. e gli dico che la domanda è molto ambigua e che non ha
ragione nessuno dei due. Non dico che voglio la risposta dalla mia, ma
almeno che non la faccia valere.....
cmq grazie

a) Assegna a B[10] il valore 7.
Per me la risposta corretta e' la A in quanto tale istruzione il
programma la esegue regolarmente (anche se poi il comportamento e'
indefinito).
Se invece usavi un vector mi sembra di ricordare che dovresti ricevere
una eccezione in fase di esecuzione .

 una eccezione in fase di esecuzione .
No. Con std::vector ricevi un'eccezione out_of_range se accedi
all'elemento N con:
vettore.at
(N)
L'operatore [] fornisce invece un accesso non controllato.
--
Gerolamo

 quanto sintatticamente esatto, è la sementica che è sbagliata.
occorre intendersi (anche col professore)
cosa significa "il compilatore non da' errore".
poiche' il mestiere del compilatore e' "compilare" il programma
e non *eseguirlo*, secondo me
il "compilatore compila correttamente quel codice".
E' compito del programmatore assicurarsi di scrivere
codice che abbia un buon comportamento,
dato che gli viene concesso di scrivere istruzioni che possono accedere
a locazioni di memoria che non ha diritto di usare/che non ha
dichiarato di voler usare.
Esempio:
int *p; // puntatore a intero, appena dichiarato
            //    non ha valore zero ma contiene
            //    un valore casuale
*p=5;    //    scrivo nella locazione puntata da p,
            //    il valore 5
questo codice compila correttamente, nessun compilatore
puo' impedirti di compilarlo dicendoti "e' sbagliato".
e' un caso perfettamente analogo al tuo problema:
scrivere b[10] o b[500] se il tuo array ha solo
10 elementi, e' una responsabilita' che i prendi tu.
NOTA: qualcuno che abbia visto solo compilatori[1] moderni,
con IDE integrato e debugger integrato e breakpoint integrato
puo' essere tratto in errore dal fatto che eseguendo il programma
il compilatore si ferma con un "Eaccess violation", o "segfault".
potrebbe dire quindi erroneamente "che il compilatore si ferma".
[1]
impropriamente viene chiamato compilatore il vc++ o
il builder, che sono vere e proprie suite che contengono
anche un compilatore

 b) Il compilatore dą errore.
la (b) e` sicuramente falsa. Sulla (a) c'e` qualche dubbio: se la 
interpretiamo come "assegna all'undicesimo elemento del vettore B il 
valore 7" e` sbagliata anch'essa, dato che questo undicesimo elemento 
non esiste.
Se la interpretiamo alla lettera:
        assegna a B[10] il valore 7
per le proprieta` dell'operatore [] diventa
        assegna a *(B+10) il valore 7
ovvero
        scrive il valore 7 nella cella di memoria B+10.
Detta cosi` la frase potrebbe anche essere accettabile, anche se quello 
che succede durante tale assegnazione e` indefinito. Infatti la 
locazione B+10 potrebbe non esistere o essere protetta dal sistema 
operativo: in questo caso il programma non riuscirebbe ad assegnare 
effettivamente il valore 7 a quella cella di memoria.
In definitiva la risposta piu` giusta e`:
"tenta di assegnare il valore 7 a B[10], ma il risultato non e` 
predicibile"
in sostanza: il tuo prof non capisce nulla di C e C++.
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 ha scritto nel messaggio
news:SfV58.8272$om6.2...@news1.tin.it...


 Erroretto :)
Attento che il Dev *NON* č un compilatore, ma č una IDE che usa un porting
dello GNU
Ciao
--
Timothy Redaelli

 
La risposta esatta e' la b: 
fabio> cat c.cpp
int B[10];
int i=9;
B[++i]=7;
fabio> g++ c.cpp
c.cpp:4: ISO C++ forbids declaration of `B' with no type
c.cpp:4: variable-size type declared outside of any function
c.cpp:4: conflicting types for `int B[2]'
c.cpp:2: previous declaration as `int B[10]'
c.cpp:4: invalid initializer
Saluti, 
Fabio  ;-)

 c.cpp:4: invalid initializer
A quanto ho capito questo č un caso in cui il compilatore puņ dare errore.
Ma puņ, nella maggior parte dei casi, non darne!
La b secondo me non č esatta.

 errore.
No. Se guardi meglio il messaggio di Fabio (in particolare il cat del
sorgente), puoi facilmente renderti conto che l'errore emesso dal
compilatore non ha nulla a che vedere con la questione discussa in questo
thread.
Max

 Antonio Cuni, 19 anni, studente
mi associo :-)
lucius

Antonio Cuni wrote:
 > Giuseppe Grillo wrote:
 >>" Dato il seguente spezzone di codice:
 >>int B[10];
 >>int i=9;
 >>B[++i]=7;
 >>
 >>a) Assegna a B[10] il valore 7.
 >>b) Il compilatore dà errore.
 >>
 >
 > la (b) e` sicuramente falsa. Sulla (a) c'e` qualche dubbio: se la
 > interpretiamo come "assegna all'undicesimo elemento del vettore B il
 > valore 7" e` sbagliata anch'essa, dato che questo undicesimo elemento
 > non esiste.
 > Se la interpretiamo alla lettera:
 >         assegna a B[10] il valore 7
 > per le proprieta` dell'operatore [] diventa
 >         assegna a *(B+10) il valore 7
 > ovvero
 >         scrive il valore 7 nella cella di memoria B+10.
 >
 > Detta cosi` la frase potrebbe anche essere accettabile, anche se 
quello
 > che succede durante tale assegnazione e` indefinito. Infatti la
 > locazione B+10 potrebbe non esistere o essere protetta dal sistema
 > operativo: in questo caso il programma non riuscirebbe ad assegnare
 > effettivamente il valore 7 a quella cella di memoria.
"I agree up to a point" :)
Da quanto ho capito leggendo il thread "Utilità dei puntatori" su
it.comp.lang.c:
1. La locazione B+10 esiste sempre e puo` essere utilizzata
nell'aritmetica dei puntatori (lo paragono all'elemento past-the-end
degli iteratori).
2. Dereferenziarla non produce comportamento indefinito. Che poi abbia
effetti collaterali sulle altre variabili del programma, e` un altro
discorso.
 > in sostanza: il tuo prof non capisce nulla di C e C++.
E su questo siamo proprio tutti d'accordo ;)
-- 
Danilo Piazzalunga
Linux Registered User #245762 at 
http://counter.li.org
mailto:
leo-...@ibero.it

 thread.
Scusa. ma è un errore?
O è solo una segnalazione del compilatore di stare attenti all'overflow?

"Giuseppe Grillo" ha scritto
:
: > No. Se guardi meglio il messaggio di Fabio (in particolare il cat del

:
L'errore sta nel fatto che non useresti l'array nel corpo di una funzione.
C'era uno smiley ;-)
ciao
Massimo

 O è solo una segnalazione del compilatore di stare attenti all'overflow?
no.
e puoi leggertelo da solo,
che non sta dicendo niente riguardo all'overflow.
...sei ancora a digiuno di inglese tecnico?

 discorso.
No.  Dereferenziarla produce comportamento indefinito (almeno in C++,
non so cosa succede in C).
B+10 e` un puntatore valido ma non dereferenziabile, puo' essere usato
solo se non si tenta di dereferenziarlo.
Per esempio e' possibile fare:
  for_each( B, B+10, fai_qualcosa );
  copy( B, B+10, da_qualche_parte );
  int * p = B+10;
  int d = p - B;
ma non:
  int i = B[10];
  B[10] = 7;
Gli effetti di queste istruzioni possono essere qualsiasi (e non solo
sulle altre variabili). La memoria all'indirizzo B+10 potrebbe essere
protetta dalla letture e/o scrittura, potrebbe non esestere, potrebbe
contenere l'indirizzo di ritorno della funzione, ...
Il compilatore potrebbe anche rifiutarsi di compilare il programma
(come in tutti i casi di undefined behaviour).
        Mauro

 2. Dereferenziarla non produce comportamento indefinito. 
falso. Dereferenziare B[10] produce proprio un comportamento indefinito.


 compila, scritto nudo e crudo.
invece compila tranquillamente. Come era facile aspettarsi:
[anto@localhost anto]$ cat prova.cc 
int i;
[anto@localhost anto]$ g++ -c prova.cc 
[anto@localhost anto]$
semmai ci saranno problemi in fase di linking, ma compilare compila.
ciao anto


> semmai ci saranno problemi in fase di linking, ma compilare compila.
la puntualizzazione e' corretta.
certo che in questo ng non puoi permetterti
di chinarti un attimo,
che subito ti incu***o...
..e' per questo che lo adoro.
ciaociao

 falso. Dereferenziare B[10] produce proprio un comportamento indefinito.
esatto, quindi l'esempio che hai scritto non e` corretto.
Alex

 l'hai scritto richiede il deferencing, e appunto:
sorry, ero distratto :-(


 ignorante non è colpa del compilatore ma è proprio il linguaggio che non
controlla lo sforamento quindi è cura del programmatore fare in modo che ciò
nn accada!
è vero il dev non è un ottimo compilatore ma funziona bene considerando che
non lo paghi!pensaci bene prima di dire cazzate!

 guarda che b[10] ti dice che la dimensione massima è dieci e l'elemento
b[10] non esiste quindi fino alla locazione b[9] puoi assegnare oltre, cioè
incrementando ( i ) sfori e non puoi allocare il compilatore come previsto
dal linguaggio nn da errore devi essere tu ad effettuare un controllo sui
limiti dell'array!il prof nn aveva ragione comunque e digli che ti ha detto
una cazzata!

 che non lo paghi!pensaci bene prima di dire cazzate!
Beh, a rapporto qualità-prezzo ci sarebbe il BCC... 

Giuseppe Grillo ha scritto : 

Facci sapere come è andata.
-- 
  _  _ >>Now on Linux<<  _     || ICQ number.................Non lo uso
 | \| |___ _____ ___ ___|_|___ || Home-Page ................Non ce l'ho
 | .` | -_|     | -_|_ -| |_ -||| E-Mail................Non l'avrai mai
 |_|\_|___|_|_|_|___|___|_|___||| Un Nemesis che ha pochi e-contatti ;)

Ma ti rendi conto il tuo "CANDIDO" post che cosa ha generato???
Ma in che mondo viviamo! :^)

Cioč non dovevo fare questa domanda.............?
