PDA

Visualizza la versione completa : [C++] array e aritmetica dei puntatori


hfish
29-12-2004, 18:22
c' qualcosa che non mi torna...
se dichiaro un array di 10 elementi, viene allocata memoria solo e soltanto per quei dieci elementi...

se per caso dovessi assegnare un dato valore ad un ipotetico undicesimo elemento, commetterei un errore logico, in quanto questo valore verrebbe scritto in una zone di memoria che non so a cosa corrisponde...



int prova_array[] = { 1, 2, 3, 4 };
for (int i = 0; i < 4; i++) {
cout << prova_array[i] << '\n';
}
cout << '\n';

for (int i = 0; i < 4; i++) {
cout << *(prova_array + i) << '\n';
}
cout << '\n';

questo codice fa tranquillamente il suo lavoro stampando tutti i valori dell'array, sia incrementando l'indice che usando l'aritmetica dei puntatori


a questo punto per provo a scrivere


prova_array[7] = 15;
for (int i = 0; i < 8; i++) {
cout << prova_array[i] << '\n';
}
cout << '\n';

for (int i = 0; i < 8; i++) {
cout << *(prova_array + i) << '\n';
}
cout << '\n';


e maledizione funziona anche questo codice :dh:

ovviamente i valori di prova_array[4], [5] e [6] sono presi non so dove dallo stack, ma il valore [7] corrisponde a quello che ho immesso io...

se una cosa del genere posso (forse) capirla incrementando l'indice, utilizzando l'aritmetica dei puntatori proprio non mi ritrovo :dh: :dh: :dh: :dh: :dh:

eagle_fly
29-12-2004, 18:53
questo succede perch quando crei un vettore il compilatore si occupa lui dell'allocazione di tutti i suoi elementi nello stack, perci anche se te immetti effettivamente un valore in una sola cella le altre sono comunque inizializzate con un valore qualsiasi, che sar molto raramente 0, e comunque vi sar sempre un valore, questo per la natura della memoria ram, e che dovrebbe dipendere anche dal compilatore.
Ora, anche se te usi l'aritmetica dei puntatori la medesima cosa, in quanto nella tua memoria la struttura dell'array c' quindi accedi tranquillamente via via dalla prima all'ultima cella del vettore!!

nome_vettore | -1211313 |
nome_vettore + 1 | -1211313 |
nome_vettore + 2 | -1211313 |
nome_vettore + 3 | -1211313 |
nome_vettore + 4 | -1211313 |
nome_vettore + 5 | -1211313 |
nome_vettore + 6 | -1211313 |
nome_vettore + 7 | 15 |

la struttura della tua memoria a grandi linee (tenendo conto che ogni elemento del vettore occupa 4 celle di memoria o 2 in base che sia di tipo int o short, o altre dipendentemente dal tipo di dato) e come quella sopra con tutti i valori inizializzati con un valore random, ma comunque effettivamente presenti nella memoria. Il fatto che il compilatore crei questa struttura legato all'uso che si fa della ram. Spero di aver chiarito un p i tuoi dubbi ma soprattutto di essere stato corretto!!!

CIAO

hfish
29-12-2004, 19:12
Originariamente inviato da eagle_fly
questo succede perch quando crei un vettore il compilatore si occupa lui dell'allocazione di tutti i suoi elementi nello stack, perci anche se te immetti effettivamente un valore in una sola cella le altre sono comunque inizializzate con un valore qualsiasi, che sar molto raramente 0, e comunque vi sar sempre un valore, questo per la natura della memoria ram, e che dovrebbe dipendere anche dal compilatore.
Ora, anche se te usi l'aritmetica dei puntatori la medesima cosa, in quanto nella tua memoria la struttura dell'array c' quindi accedi tranquillamente via via dalla prima all'ultima cella del vettore!!

nome_vettore | -1211313 |
nome_vettore + 1 | -1211313 |
nome_vettore + 2 | -1211313 |
nome_vettore + 3 | -1211313 |
nome_vettore + 4 | -1211313 |
nome_vettore + 5 | -1211313 |
nome_vettore + 6 | -1211313 |
nome_vettore + 7 | 15 |

la struttura della tua memoria a grandi linee (tenendo conto che ogni elemento del vettore occupa 4 celle di memoria o 2 in base che sia di tipo int o short, o altre dipendentemente dal tipo di dato) e come quella sopra con tutti i valori inizializzati con un valore random, ma comunque effettivamente presenti nella memoria. Il fatto che il compilatore crei questa struttura legato all'uso che si fa della ram. Spero di aver chiarito un p i tuoi dubbi ma soprattutto di essere stato corretto!!!

CIAO
nello stack dovrei avere una cosa del genere
array0 | 1
array1 | 2
array2 | 3
array3 | 4

una volta che scrivo prova_array[7] = 15, perch questo si accoda automaticamente ad array3??? ho provato anche ad inizializzare altre var nel mezzo, giusto per occupare un po' di spazio, ma il risultato non cambia...

prova_array[7] dovrebbe essere allocato in un una cella a caso dello stack, chiss dove... invece continua a finire subito dopo array3 :nonlodire

anx721
29-12-2004, 23:15
uso MInGW come compilatore. e il valore 15 che dai alla ottava locazione dell'array non va a finire subito dopo prova_array[3], ma va nell'ottava locazione; questo l'output del programma , prima di andare in crash a causa dell'accesso errato in memoria:

1
2
3
4
4008320
0
2293680
15


come vedi le prime quattro locazioni sono quelle correttamente inizializzate con la dichiarazione dell'array; poi ci sono tre posizioni, dalla quinta alla settima, che hanno dei valori a caso, e infine l'ottava, corroispondente a prova_array[7], che ha il valore 15; l'output lo stesso anche con l'aritmetica dei puntatori; anzi in genere i compilatori trasformano automaticamente a[i] in *(a + i)

netarrow
29-12-2004, 23:20
la memoria obbligatoria allocarla solo nel caso dei puntatori, il tuo array contiene valori.

Se dichiari:

int* a;//LA MEMORIA NON E' ALLOCATA E TANTO MENO INIZIALIZZATA

int a;//la memoria allocata ma non inizializzata

Come esempio riporto un programma che ha un array di puntatori a interi:



#include <iostream>

using namespace std;

int main() {
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int t = 5;
int *q[] = {&a,&b,&c,&d};

q[5] = &t;

for(int i = 0; i < 5; i++) {
cout << *q[i] << " ";
}


return 0;
}


Eseguendo normalmente, vediamo scrivere: 1 2 3 4... e il 5? Non si vede, allora facciamo un debug e... eccolo! Access Violation! E l'indirizzo incriminato proprio lui: 0xC0000005.
Quindi avremo:

0xC0000001 = 1
0xC0000002 = 2
0xC0000003 = 3
0xC0000004 = 4
----------------
0xC0000005 = 5// gli do il valore 5 senza aver allocato => Access Violation


Ho fatto adesso gli esperimenti, e nella speranza di non aver detto cacate, ciao

hfish
30-12-2004, 14:07
Originariamente inviato da anx721
uso MInGW come compilatore. e il valore 15 che dai alla ottava locazione dell'array non va a finire subito dopo prova_array[3], ma va nell'ottava locazione; questo l'output del programma , prima di andare in crash a causa dell'accesso errato in memoria:


appunto... :) :) non dovrebbe essere nell'ottava locazione, ma in una a caso :)

io uso devcpp e il prog non abortisce

anx721
30-12-2004, 21:49
appunto... non dovrebbe essere nell'ottava locazione, ma in una a caso

E perch mai?

In C non si effetuano a runtime controlli sui limiti degli array, quindi quando scrivi

a[i] = xxx ;

il compilatore sa semplicemente che deve scrivere il valore xxx nella i-esima locazione a partire da quella puntata da 'a', non in una posizione a caso; se poi questa locazione apartiene o meno all'array non importa, sta al programmatore occuparsi di questo. Quindi se tu scrivi

prova_array[7] = 15

il compilatore va a scrivere nell'ottava posizione di memoria (tenendo conto della dimensione degli int) a partire dalla locazione puntata dal puntatore prova_array, il fatto che tale locazione non appartenga piu all'array ma chissa a cosa ignoto al compilatore, che si limita a effettuare la scrittura;

quindi non c' nulla di cui stupirsi.

Dev-cpp non un compilatore, ma semplicemente un editor, che viende distribuito generalmente assieme ad un compilatore, che nelle ultime versioni proprio MinGW; nelle versioni precedenti non so con che compilatore venisse distribuito. Il verificarsi o meno del crash puo dipedere dal compilatore e/o dal sistema operativo.

hfish
31-12-2004, 09:41
Originariamente inviato da anx721
E perch mai?

In C non si effetuano a runtime controlli sui limiti degli array, quindi quando scrivi

a[i] = xxx ;

il compilatore sa semplicemente che deve scrivere il valore xxx nella i-esima locazione a partire da quella puntata da 'a', non in una posizione a caso; se poi questa locazione apartiene o meno all'array non importa, sta al programmatore occuparsi di questo. Quindi se tu scrivi

prova_array[7] = 15

il compilatore va a scrivere nell'ottava posizione di memoria (tenendo conto della dimensione degli int) a partire dalla locazione puntata dal puntatore prova_array, il fatto che tale locazione non appartenga piu all'array ma chissa a cosa ignoto al compilatore, che si limita a effettuare la scrittura;

quindi non c' nulla di cui stupirsi.

Dev-cpp non un compilatore, ma semplicemente un editor, che viende distribuito generalmente assieme ad un compilatore, che nelle ultime versioni proprio MinGW; nelle versioni precedenti non so con che compilatore venisse distribuito. Il verificarsi o meno del crash puo dipedere dal compilatore e/o dal sistema operativo.
il secondo capoverso del mio primo post l'ho preso pari pari da
INTRODUZIONE ALLA PROGRAMMAZIONE ED ELEMENTI DI STRUTTURE DATI CON IL LINGUAGGIO C++, pag 115, cap 9.2

anx721
31-12-2004, 11:15
Originariamente inviato da hfish
il secondo capoverso del mio primo post l'ho preso pari pari da
INTRODUZIONE ALLA PROGRAMMAZIONE ED ELEMENTI DI STRUTTURE DATI CON IL LINGUAGGIO C++, pag 115, cap 9.2


Immagino che ti riferisci a questo:


se per caso dovessi assegnare un dato valore ad un ipotetico undicesimo elemento, commetterei un errore logico, in quanto questo valore verrebbe scritto in una zone di memoria che non so a cosa corrisponde...


Questa frase non significa che la locazione di memoria in cui vado a scrivere non so quale sia...la locazione di memoria in cui scrivo la so e come...ed appunto quella che ottengo a partire dal puntatore e andando avanti per 11 posizioni, ed il meccanismo che usa il compilatore per scrivere in un array, idipendentemente dal fatto che l'indice in cui vado a scrivere sia o no entro i limiti dell'array stesso. l'espressione:

"questo valore verrebbe scritto in una zona di memoria che non so a cosa corrisponde"

significa invece che quella locazione in cui vado a scrivere non so cosa contenga, se una locazione che stata riservata per un altra variabile, se non ancora utilizzata dal programma, o se ci sono altri dati; in ogni caso un errore che puo causare il crash del programma

hfish
31-12-2004, 13:34
Originariamente inviato da anx721
Immagino che ti riferisci a questo:



Questa frase non significa che la locazione di memoria in cui vado a scrivere non so quale sia...la locazione di memoria in cui scrivo la so e come...ed appunto quella che ottengo a partire dal puntatore e andando avanti per 11 posizioni, ed il meccanismo che usa il compilatore per scrivere in un array, idipendentemente dal fatto che l'indice in cui vado a scrivere sia o no entro i limiti dell'array stesso. l'espressione:

"questo valore verrebbe scritto in una zona di memoria che non so a cosa corrisponde"

significa invece che quella locazione in cui vado a scrivere non so cosa contenga, se una locazione che stata riservata per un altra variabile, se non ancora utilizzata dal programma, o se ci sono altri dati; in ogni caso un errore che puo causare il crash del programma
ok, ora ho capito... interpretavo male la frase io...

grazi x il tempo perso...
auguri
:ciauz:

Loading