PDA

Visualizza la versione completa : [C++] Uso degli array: dimensionamento e valorizzazione


programfile
27-01-2011, 20:50
Salve a tutti, questo il mio primo post.
Avrei un piccolo problema con gli array (vettori) nel C++.
Dunque ora cerco di spiegare bene con un esempio perch cos si capisce meglio.



#include <iostream>
using namespace std;

int main () {
const int dim = 4;
int misure[dim];

int muse[5] = {4, 6, 3, 7, 8};

misure[0]= 45;
misure[1]= 37;
misure[2]= 29;
misure[3]= 56;
*
cout << misure[2] << endl;
cout << muse[3] << endl;
**
}

return 0;
}

Questo codice mi viene compilato ed eseguito correttamente. (Correggetemi se sbaglio).
SE invece aggiungo nel codice questa porzione di codice:

*misure[7]= 35;

**cout << misure[7] << endl;

Il programma (DEV C++) mi compila correttamente il codice e me lo esegue anche correttamente!!! Cio mi stampa a video il valore di "misure[7]" anche se nell'intestazione c' scritto chiaramente che il vettore ha dimensione 4.
Lo stesso vale anche con il secondo vettore dichiarato. Per non creare confusione non aggiungo altro, ma se nel codice scrivessi lo stesso errore per il vettore muse, come per il vettore misure, il programma compila ed esegue.

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++?


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)?


Ringrazio sentitamente chi riuscir a chiarirmi questi dubbi amletici :confused:
PS: spiegate anche le motivazioni :D Grazie!!!

shodan
27-01-2011, 21:48
Ne C ne C++ controllano un eventuale sforamento dei limiti massimi dell'array, e cosa succede, quando avviene, ricade nel "comportamento indefinito" (undefined behaviour).



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.

Corretto.


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?

Perch una porcheria introdotta nel gcc e poi ratificata nello standard ISO C99 che prevede i VLA ( variable length array ). A quanto ne so funziona solo su gcc e i vari porting, ma non su altri compilatori. Il C++ non prevede questa ciofeca e giustamente si rifiuta di compilare se gliela proponi. Attualmente, poi, DEVC++ un insulto, non un compilatore.
Il mio consiglio passare a VC++ Express o ( se non ti piace M$ ) a CodeBlocks ( di cui trovi vari porting).

MItaly
27-01-2011, 22:01
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).

programfile
27-01-2011, 22:09
Originariamente inviato da shodan
Ne C ne C++ controllano un eventuale sforamento dei limiti massimi dell'array, e cosa succede, quando avviene, ricade nel "comportamento indefinito" (undefined behaviour).

Quindi l'unico metodo controllare e ricontrollare mille volte il codice perch solo io (o cmq il programmatore) pu controllare che tutto sia giusto comprese le dimensioni e i valori dell'array, altrimenti tutto mi si compila come se niente fosse. Giusto?
Perch quando lo compilo con la dimensione sbagliata non che mi restituisce un valore random, no, mi restituisce il valore che ho definito io anche se fuori dall'array!
Quindi per questo problema colpa del compilatore oppure solamente il linguaggio che non controlla?


Originariamente inviato da shodan
Perch una porcheria introdotta nel gcc e poi ratificata nello standard ISO C99 che prevede i VLA ( variable length array ). A quanto ne so funziona solo su gcc e i vari porting, ma non su altri compilatori. Il C++ non prevede questa ciofeca e giustamente si rifiuta di compilare se gliela proponi. Attualmente, poi, DEVC++ un insulto, non un compilatore.
Il mio consiglio passare a VC++ Express o ( se non ti piace M$ ) a CodeBlocks ( di cui trovi vari porting).
In questo secondo caso quindi solo colpa del compilatore? Se compilassi con altri programmi questi mi si rifiuterebbero di compilare ci che ho scritto sopra?

I programmi che mi citi sono gratis o a pagamento? (scusate l'ignoranza! :D )
Grazie mille per la risposta!!!

MItaly
27-01-2011, 22:20
Originariamente inviato da programfile
Quindi l'unico metodo controllare e ricontrollare mille volte il codice perch solo io (o cmq il programmatore) pu controllare che tutto sia giusto comprese le dimensioni e i valori dell'array, altrimenti tutto mi si compila come se niente fosse. Giusto?
Perch quando lo compilo con la dimensione sbagliata non che mi restituisce un valore random, no, mi restituisce il valore che ho definito io anche se fuori dall'array!
Non necessariamente. Se poi scrivi nella memoria dove hai scritto questo valore in maniera "corretta" ti ritrovi un altro valore.


Quindi per questo problema colpa del compilatore oppure solamente il linguaggio che non controlla?
undefined behavior definito a livello di linguaggio.

In ogni caso, in generale puoi utilizzare la classe template std::vector (parte della libreria standard) e usare il metodo at per accedere agli elementi, che controlla sempre l'indice passato.



In questo secondo caso quindi solo colpa del compilatore? Se compilassi con altri programmi questi mi si rifiuterebbero di compilare ci che ho scritto sopra?
No; tuttavia, se sfori un array in modo cos palese da sforare anche dallo stack frame (sovrascrivendo l'indirizzo di ritorno) i compilatori moderni fanno s che il tuo programma si arresti con un errore invece di andare avanti in uno stato incoerente ( una protezione contro gli attacchi di stack-smashing).


I programmi che mi citi sono gratis o a pagamento? (scusate l'ignoranza! :D )
Grazie mille per la risposta!!!
Sono entrambi gratis. Nota comunque che Code::Blocks e Dev-C++ sono due IDE diverse, il compilatore che ci sta sotto lo stesso (MinGW, il porting per Windows di g++); tuttavia dato che Dev-C++ ha cessato lo sviluppo diversi anni fa ti ritrovi una versione piuttosto vecchia di MinGW, mentre con Code::Blocks hai le versioni pi recenti.

shodan
27-01-2011, 22:32
Un altro compilatore gratis, compatibile con Codeblocks, Borland C++ 5.5.1 ( da qualche parte nel sito di Embarcadero), ma non hai il debugger.
E' comunque una buona alternativa per farsi le ossa.

Diciamo che va bene tutto tranne DEVC++

programfile
27-01-2011, 22:32
Originariamente inviato da MItaly
In ogni caso, in generale puoi utilizzare la classe template std::vector (parte della libreria standard) e usare il metodo at per accedere agli elementi, che controlla sempre l'indice passato.

Non l'ho mai usata... come funziona?


Originariamente inviato da MItaly
Sono entrambi gratis. Nota comunque che Code::Blocks e Dev-C++ sono due IDE diverse, il compilatore che ci sta sotto lo stesso (MinGW, il porting per Windows di g++); tuttavia dato che Dev-C++ ha cessato lo sviluppo diversi anni fa ti ritrovi una versione piuttosto vecchia di MinGW, mentre con Code::Blocks hai le versioni pi recenti.
Quindi...DEV un p vecchiotto...
Bhe allora mi sa che cambio compilatore! :D
Volevo chiedere... possibile avere dei link dove scaricare questi due software visto che sono gratis oppure no?
Se vado contro il regolamento con questa richiesta chiedo anticipatamente scusa.

MItaly grazie per le risposte esaustive che mi hai fornito :D



Originariamente inviato da shodan
Un altro compilatore gratis, compatibile con Codeblocks, Borland C++ 5.5.1 ( da qualche parte nel sito di Embarcadero), ma non hai il debugger.
E' comunque una buona alternativa per farsi le ossa.

Diciamo che va bene tutto tranne DEVC++
Borland? Ma...ehm..scusatemi l'ignoranza, ma questo non era a pagamento?

MItaly
27-01-2011, 22:47
Originariamente inviato da programfile
Non l'ho mai usata... come funziona?
Ti rimando alla sua documentazione di riferimento (http://www.cplusplus.com/reference/stl/vector/), nelle pagine dei vari metodi ci sono anche un po' di esempi.


Quindi...DEV un p vecchiotto...
Bhe allora mi sa che cambio compilatore! :D
Volevo chiedere... possibile avere dei link dove scaricare questi due software visto che sono gratis oppure no?
Se vado contro il regolamento con questa richiesta chiedo anticipatamente scusa.
Microsoft Visual C++ Express Edition (http://www.microsoft.com/express/Downloads/#2010-Visual-CPP) (quando crei un nuovo progetto scegli progetto console nativo win32)
Code::Blocks (http://www.codeblocks.org/downloads/26) (mi raccomando scegli il download con MinGW incluso)
Ho sentito parlare bene anche di CodeLite (http://www.codelite.org/) (download (http://sourceforge.net/projects/codelite/files/Releases/codelite-2.9/codelite-2.9.0.4684-mingw4.4.1-wx2.8.10.exe/download)); nota che anche lui di base usa come compilatore MinGW, per cui dal punto di vista del compilatore usato non differisce da Code::Blocks.


MItaly grazie per le risposte esaustive che mi hai fornito :D
Non c' di che. :)


Borland? Ma...ehm..scusatemi l'ignoranza, ma questo non era a pagamento?
Il compilatore e basta gratuito; lo puoi usare in abbinata ad un editor qualunque e alla linea di comando o a IDE come Code::Blocks (che supportano diversi compilatori).

programfile
27-01-2011, 23:03
Originariamente inviato da MItaly
Microsoft Visual C++ Express Edition (http://www.microsoft.com/express/Downloads/#2010-Visual-CPP) (quando crei un nuovo progetto scegli progetto console nativo win32)
Code::Blocks (http://www.codeblocks.org/downloads/26) (mi raccomando scegli il download con MinGW incluso)
Ho sentito parlare bene anche di CodeLite (http://www.codelite.org/) (download (http://sourceforge.net/projects/codelite/files/Releases/codelite-2.9/codelite-2.9.0.4684-mingw4.4.1-wx2.8.10.exe/download)); nota che anche lui di base usa come compilatore MinGW, per cui dal punto di vista del compilatore usato non differisce da Code::Blocks.

Il compilatore e basta gratuito; lo puoi usare in abbinata ad un editor qualunque e alla linea di comando o a IDE come Code::Blocks (che supportano diversi compilatori).
Grazie mille!!
Bene allora provo questi programmi :)
Se poi ho problemi posto ancora!!! :D
Grazie ancora!!!

MItaly
28-01-2011, 00:01
:ciauz:

Loading