Pages: 1 [2]   Go Down
Author Topic: Ridimensionare array  (Read 1069 times)
0 Members and 1 Guest are viewing this topic.
Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2742
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
da quando questo? a me non risulta, anzi ci sarà dentro l'ultimo valore memorizzato
Sì certo, anche tu hai ragione, ma non avendo scritto programmi più lunghi di 58k dovrò trovare delle celle vergini, almeno che per un pezzo siano tutte uguali smiley quello dovrebbe farti capire che da un certo punto in poi non c'è mai stato nessuno smiley

la program memory parte da 0x0000
« Last Edit: January 23, 2013, 12:48:20 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21619
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@pablos:
il bootloader occupa sempre la parte più alta della memoria Flash.

@lesto:
una cella FLASH o EEPROM erasata contiene $FF come valore "vuoto".
Logged


Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2742
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho letto un testo di Banzi dove uno schema a blocchi mette memory program 0x0000 e il boot lo mette in fondo comunque fa lo stesso a me serve il centro ahahahahah.

@Astro il link che hai messo http://www.nongnu.org/avr-libc/user-manual/pgmspace.html mi scrive dei byte prestabiliti usando uno spazio della flash,
vedo solo dei pgm_read, ma non dei pgm_write
io chiedo di poter scrivere su una cella della flash come faccio con la eeprom a prescindere che rischio di andare sopra allo sketck , che istruzioni devo usare per leggere e scrivere su una posizione?

grazie ciao
Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Se tu avessi un vettore v1 di dimensione x e vorresti avere un vettore v2 di dimensione y allora devi chiamare la funzione che ho scritto come nel seguente modo:

int * v2 = changeDim(v1, y);

A questo punto v2 contiene l'indirizzo a partire dal quale è memorizzato l'array in memoria.

Code:

int* changeDim(int* vector, int newDim){
    if (vector != 0 ){
        int* newArray = new int[newDim];
        int vectorLen = newDim;
        for (int var = 0; var < vectorLen; ++var)
            newArray[var] = vector[var];

        return newArray;
    }
    else
        return (int*)0;
}

La mia funzione restituisce vettore di iteri ma basta cambiare il tipo per ottenere un vettore di diverso tipo.
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10105
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ci sono 3 errori:
1. stai creando garbage non distruggendo il vecchio vettore (il c++ non ha un garbage collector come java o simili, la spazzatura la si porta fuori a manina)
2. alla funziona non puoi passare un array, poichè un array ha indirizzo costante, e quindi non modificabile tramite malloc o new
3. dai per scontato che la "new" abbia successo, cosa non vera. se non c'è ram disponibile la new/malloc ritorna NULL

ci sono anche 3 imprecisazioni secondo me:
1. stai confondendo new (usato per le classi) con malloc e compagnia bella (la new in realtà poi chiama la malloc, ma il punto è che confondi C e C++ inutilmente)
2. prima di fare una malloc prova a fare una realloc: questa non solo POTREBBE (non ne sono sicuro) funzionare anche con gli array, visto che non modifica la posizione dell'array ma cerca solo di espanderlo, ma appunto per questo comportamento non è necessario copiare il contenuto del vecchio vettore in quello nuovo risparmiando un sacco di cicli macchina, senza contre che nella fase di copia evita di occupare quasi il doppio di RAM necessaria dal tuo metodo (vecchio vettore + nuovo vettore).
lo svataggio della realloc() è che spesso fallisce perchè subito dopo l'array la RAM è già usata da altre variabili... in tal caso si fa il fall-back a malloc
3.
Code:
return (int*)0;
è illeggibile, non sono neanche sicuro di interpretarla bene. forse intendevi
Code:
return null;
« Last Edit: February 04, 2013, 08:32:24 am by lesto » Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21619
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

lesto, non so se te ne sei accorto ma nelle ultime versioni dell'IDE (non so se è già presente nella 1.0.3 perché io ho una 1.0.4 beta, compilando spesso dai sorgenti) sono stati inseriti new e malloc anche nell'Arduino.
Se guardi in core/Arduino trovi i file malloc.c, new.cpp e new.h
In new.h si legge poi:
Quote
Header to define new/delete operators as they aren't provided by avr-gcc by default
Non sapevo che avr-gcc non gestisse new e malloc... mi suona strano
Logged


0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10105
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

leo non metto in dubbio questo, le malloc sono sempre esistite, altrimenti non avresti tutto ciò che usa RAM in modo dinamico (anzi, mi sa tutto ciò che usa ram).
La NEW non esisteva ed è stata aggiunta, ma comunque poteva essere creata ad-hoc, visto che come dicevo alla fine non è altro che una malloc con un poco di logica in più, e la delete è una free.

Quello che sto cercando di far capire è che quelle funzioni sono usate in modo magari non errato, ma sicuramente molto border-line, sicuramente non da dare a cuor leggero a chi non capisce cosa sia un puntatore (reply #2)

osservando meglio l'empio di uso postato, alessandro87 ha correttamente usato un puntatore per ricevere il risultato, e non ha sovrascritto perdendo per sempre l'indirizzo di v1, creando garbage.
corretto:
Code:
int * v2 = changeDim(v1, y);

quello che mi aspeto facia un principiante:
Code:
v1 = changeDim(v1, y); //errore, la vecchia zona di memoria di v1 è diventata garbage ovvero non più utilizzabile perchè contrassegnata come allocata, ma non più utilizzabile/deallocabile perchè non sappiamo più dov'è

rimane comunque sicuramente l'errore del punto 3. e anzi, aggiungerei un punto 4. nelle "imprecisazioni secondo me": mi sono lamentato della return ma non della
Code:
if (vector != 0)
che è più leggibile come
Code:
if (vector != null)

quindi:

Code:
int* changeDim(int* vector, int newDim){
    if (vector != null ){
        int* newArray = realloc( newDim*sizeof(int) );
        if (newArray != null){
            vector = newArray ;
            return vector;
        }
        newArray = malloc( newDim*sizeof(int) );
        if (newArray != null){
            for (int var = 0; var < newDim; ++var)
                newArray[var] = vector[var];
            free(vector);//dealloca la ram
            vector = newArray;
            return vector;
         }
    }
    return null;
}
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao lesto,

Per quanto riguarda gli "errori":
1) Il vecchio vettore non si può distruggere perché è creato staticamente infatti nel primo post carletto scriveva che aveva un vettore fatto cosi: byte mioarray[35]. E comunque alla mia funzione non interessa quello che accade sopra e anche se gli interessasse non è di certo sua la responsabilità di eliminare oggetti posti fuori dalla sua scope .
2) Alla funzione passo l'indirizzo a partire dal quale è memorizzato l'array in memoria, non voglio modificare nulla voglio soltanto leggere i valori presenti.
3) Qua ti do ragione.. ma un gioco con arduino non è safety critical. In altre circostanze c'è da tenere conto di questo aspetto.

Per quanto riguarda le imprecisioni
1) Arduino permette l'utilizzo del c++ e io programmo in c++ perchè mi piace di piu e perchè è a oggetti. (conosco gente che programma a oggetti anche con il c ma questo non fa per me)
2) Ho deciso di copiare i vecchi numeri per gioco.
3) (int*) 0 è un exp e si legge cosi: 0 è una var e faccio il cast a puntatore intero. Equivalente a fare questo int* var = 0; return var;(leggi la grammatica del c++) inoltre in c++ la definizione di NULL è 0. http://www.stroustrup.com/bs_faq2.html#null .

E ultima cosa ecco i tuoi errori:

Prova.cpp: In function ‘int* changeDim(int*, int)’:
Prova.cpp:31:19: error: ‘null’ was not declared in this scope
Prova.cpp:32:53: error: invalid conversion from ‘unsigned int’ to ‘void*’ [-fpermissive]
Prova.cpp:32:53: error: too few arguments to function ‘void* realloc(void*, size_t)’
In file included from /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h:4:0,
                 from Blink.cpp:10:
/usr/lib/gcc/avr/4.7.2/../../../avr/include/stdlib.h:338:14: note: declared here
Prova.cpp:37:47: error: invalid conversion from ‘void*’ to ‘int*’ [-fpermissive]
Prova.cpp:46:12: error: ‘null’ was not declared in this scope

Come puoi notare nell'ultima riga: ‘null’ was not declared in this scope.

Grazie e ciao  smiley-razz
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10105
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok i punti  1 e 2 però
Quote
ma un gioco con arduino non è safety critical. In altre circostanze c'è da tenere conto di questo aspetto.
insomma. la ram esaurita è una delle cose più difficili da debuggare su un'arduino, e cose del geenre non aiutano.

Quote
(conosco gente che programma a oggetti anche con il c ma questo non fa per me)
vorrei conoscere questa gente... il C non è ad oggetti, si può simulare il comportamento degli oggetti... e in pratica riscrivi il C++  smiley-mr-green

Quote
E ultima cosa ecco i tuoi errori:

hai ragione, scivo il codice a lavoro e ogni tanto dimentico di avvisare che non è nemmeno testato in compilazione.
Comunque NULL invece che null, la realloc vuole anche il puntatore all'array da incrementare, e tulle le alloc ritorano un puntatore a void (generico) che va castato in quello che ti interessa

codice compilabile:
Code:
int* changeDim(int* vector, int newDim){
    if (vector != NULL ){
        int* newArray = (int*)realloc(vector, newDim*sizeof(int) );
        if (newArray != NULL){
            vector = newArray ;
            return vector;
        }
        newArray = (int*)malloc( newDim*sizeof(int) );
        if (newArray != NULL){
            for (int var = 0; var < newDim; ++var)
                newArray[var] = vector[var];
            free(vector);//dealloca la ram
            vector = newArray;
            return vector;
         }
    }
    return NULL;
}

volendo si possono usare i puntatori void per rendere la funzione più generica (notare che non si possono usare gli indici o giocare con gli indirizzi nei puntatori void e quindi li casto ad array di byte, in alcuni compilatori non è necessario):

Code:
void* changeDim(void* vector, int newDim, int sizeOfType){
    if (vector != NULL ){
        void* newArray = realloc(vector, newDim*sizeOfType );
        if (newArray != NULL){
            vector = newArray;
            return vector;
        }
        newArray = malloc( newDim*sizeOfType );
        if (newArray != NULL){
            for (int var = 0; var < newDim*sizeOfType; var++)
                ((byte*)newArray)[var] = ((byte*)vector)[var];
            free(vector);//dealloca la ram
            vector = newArray;
            return vector;
         }
    }
    return NULL;
}

esempio di uso
Code:
int* array = (int*)malloc(sizeof(int)*16); //da 16
array = (int*)changeDim(array, 20, sizeof(int)); //a 20

edit:in fine ricorderei che non ci troviamo davanti a vero C o vero C++, tantè che fino a 5 o 6 mesi fa non esisteva la new o la delete.
« Last Edit: February 04, 2013, 06:35:38 pm by lesto » Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bene.. sarà contento adesso carletto di avere queste soluzioni! Ciaoo e buonanotte
Logged

Pages: 1 [2]   Go Up
Jump to: