Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

puntatori ed array

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] puntatori ed array

Messaggioda Foto UtenteMarcRider » 2 ott 2013, 22:17

Non sono abituato ad usare i puntatori, e non riesco a digerirli troppo, ho comunque una esigenza, ed ho scritto questa funzione:

Codice: Seleziona tutto
  char* ToArrayChar(char numero)
{
       char MioDato[3];

       if (numero > 100)
    {
     
        MioDato[2] = (numero % 10) + 48;
        MioDato[1] = ((numero / 10) % 10)+48;
        MioDato[0] = (numero / 100)+48;

       
    } else if (numero > 10)
    {
       
        MioDato[1] = (numero % 10)+48;
        MioDato[0] = (numero / 10)+48;
       
    }else if (numero < 10)
    {
       
        MioDato[0] = (numero + 48);
       
    }

return MioDato;

}


Ho provato a recuperarla con una funzione che accetta come argomento un array, il codice non da errore, ma quando gli passa l'array, lo riscontro vuoto con zero elementi.

Ho sbagliato a scrivere?
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

4
voti

[2] Re: puntatori ed array

Messaggioda Foto UtenteTardoFreak » 2 ott 2013, 22:35

A parte una serie di considerazioni su come passare gli array come parametri ...

La tua funzione non funziona perché la tua array esiste solo ed esclusivamente all' interno della funzione e per il tempo in cui la funzione viene eseguita.
In buona sostanza, quando chiami la funzione
- questa alloca l' array nello stack
- ci lavora sopra
- ritorna il puntatore all' array (che però è nello stack)
- all' uscita libera lo stack dall' array, questa non esiste più ed il puntatore punta ad una locazione che non ha più senso.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

2
voti

[3] Re: puntatori ed array

Messaggioda Foto UtenteGuidoB » 3 ott 2013, 0:22

Potresti passare l'array come parametro, oppure dichiarare l'array come static, così non viene allocato sullo stack e continua ad esistere anche una volta usciti dalla funzione.

Il secondo modo fa storcere un po' il naso, parché da fuori accederesti a un dato in un certo senso "privato" della funzione. Però è un sistema che funziona e viene usato anche in programmi "seri", sia per comodità (non doversi allocare un array e passare il puntatore ogni volta che si chiama la funzione), sia per cautelarsi contro l'eventualità che l'array passato abbia una dimensione insufficiente, sia per far assomigliare la chiamata a quella di linguaggi tipo Java (dove ci pensa la funzione ad allocarti una stringa e te la restituisce, poi tu non devi preoccuparti di ritornare la memoria perché ci pensa automaticamente il garbage collector).
Se la frase precedente ti sembra arabo salta pure per il momento e andiamo avanti.

Nel tuo codice vedo qualche altro problema:

1) "numero" è dichiarato come char. E se fosse negativo? Cambierei la dichiarazione a "unsigned char" così siamo sicuri che è sempre positivo;

2) presumo che vorrai utilizzare l'array di char come una stringa. In tal caso devi mettere alla fine il carattere di terminazione '\0' e prevedere anche lo spazio per contenerlo (aggiungere 1 alla dimensione dell'array);

3) sarebbe meglio definire la lunghezza della stringa in una costante (#define LUNGHEZZA 3) e poi usare sempre la costante in tutti i posti in cui ti serve;

4) il numero 48 (codice ASCII del carattere '0') sta proprio male. Il poveraccio che dovrà fare una modifica a quella funzione, se non sa a memoria i codici ASCII si scervellerà per capire che cos'è quel 48. E se il computer non utilizzasse l'ASCII ma un altro set di caratteri? Scrivi '0' (carattere 0) al posto di 48 (numero 48) e risolvi elegantemente il problema. Ci pensa il C a trattarlo come numero;

5) sarebbe meglio evitare tutti quegli "if" e "else if" con codice ripetuto, cercando una soluzione più universale.

Io farei così:
Codice: Seleziona tutto
#define LUNGHEZZA 3

/* altro codice qui in mezzo... */

    char* ToArrayChar(unsigned char numero)
    {
        static char MioDato[LUNGHEZZA + 1];
        char *p = MioDato + LUNGHEZZA;

        *p = '\0';

        do
        {
            p  = p - 1;
            *p = numero % 10 + '0';
            numero = numero / 10;           
        }
        while (numero > 0);

        return p;
    }


oppure, in modo un po' più criptico ma (si spera) più efficiente:
Codice: Seleziona tutto
#define LUNGHEZZA 3

/* altro codice qui in mezzo... */

    char* ToArrayChar(unsigned char numero)
    {
        static char MioDato[LUNGHEZZA + 1];
        char *p = MioDato + LUNGHEZZA;

        *p = '\0';

        do
        {
           *--p = numero % 10 + '0';
        }
        while (numero /= 10);

        return p;
    }


Devi tener presente che ogni chiamata alla funzione distrugge il valore ritornato dalla chiamata precedente.
Quindi devi usare il valore ritornato prima di effettuare una nuova chiamata, oppure conservarlo ricopiandolo in un'altra stringa.
Big fan of ƎlectroYou!       Ausili per disabili e anziani su ƎlectroYou
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
Avatar utente
Foto UtenteGuidoB
17,8k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 2809
Iscritto il: 3 mar 2011, 16:48
Località: Madrid

0
voti

[4] Re: puntatori ed array

Messaggioda Foto UtenteMarcRider » 3 ott 2013, 9:44

grazie mille dellw risposte ultra esaurienti ed immediate.

ho una curiosita ,una volta che l'array non mi serve più , con static resta nella memoria? se riutilizzo la funzione, mi crea un'altra variabile static o riutilizza sempre la stessa?

appena stacco da lavoro, scriverò la nuova funzione pulita e commentata, cosi magati puo essere utile a qualcunaltro.
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

0
voti

[5] Re: puntatori ed array

Messaggioda Foto UtenteGuidoB » 3 ott 2013, 9:57

Ciao,
MarcRider ha scritto:ho una curiosita ,una volta che l'array non mi serve più , con static resta nella memoria?

Sì.

Comunque sono pochi byte. Se complichi il codice per liberarli, finiresti per occupare più memoria per il programma di quella che risparmieresti nei dati.

MarcRider ha scritto:se riutilizzo la funzione, mi crea un'altra variabile static o riutilizza sempre la stessa?

Riutilizza sempre la stessa.

MarcRider ha scritto:grazie mille delle risposte ultra esaurienti ed immediate
...
appena stacco da lavoro, scriverò la nuova funzione pulita e commentata, cosi magati puo essere utile a qualcunaltro.

Prego! Prova magari a scriverla in modo che possa tradurre interi più lunghi (per esempio un unsigned long) e se te la senti, prova a farla in modo che possa gestire anche interi negativi.
Big fan of ƎlectroYou!       Ausili per disabili e anziani su ƎlectroYou
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
Avatar utente
Foto UtenteGuidoB
17,8k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 2809
Iscritto il: 3 mar 2011, 16:48
Località: Madrid

1
voti

[6] Re: puntatori ed array

Messaggioda Foto UtenteTardoFreak » 3 ott 2013, 11:06

Usare la classe di memorizzazione static non è un bel modo di scrivere funzioni.
Di solito, in queste cose, si mandano come parametri il puntatore all' array e la sua dimensione.
Così facendo si scrive un codice rientrante (che è molto meglio), che si adatta a tutte le situazioni e si evitano potenziali grossi casini.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[7] Re: puntatori ed array

Messaggioda Foto UtenteGuidoB » 3 ott 2013, 13:10

Certo, se il codice deve essere rientrante non bisogna usare questo sistema.
GuidoB ha scritto:Devi tener presente che ogni chiamata alla funzione distrugge il valore ritornato dalla chiamata precedente.
Quindi devi usare il valore ritornato prima di effettuare una nuova chiamata, oppure conservarlo ricopiandolo in un'altra stringa.

Comunque sono d'accordo, è tirare il C oltre il limite delle intenzioni della classe static, infatti quando l'ho visto mi ha fatto
GuidoB ha scritto:storcere un po' il naso

Anche una variabile globale non risolve il problema (anzi peggiora ulteriormente lo stile).

Insomma fa un po' schifo. Io me ne sono ritrovata una simile per numeri a virgola mobile implementata in una libreria e l'ho dovuta usare com'era, e i casini che dici sono saltati fuori (tipo nelle sprintf che la chiamano due volte per due numeri da inserire in una stringa (*)). In quei casi dovevamo ricordarci di preparare prima le stringhe numeriche una alla volta, e poi inserirle. Suppongo che l'intenzione di chi aveva scritto la funzione era renderla comoda da usare, pensando che sarebbe stata utilizzata quasi sempre per una sola stringa alla volta, e mettendo un'avvertenza nei commenti. Ma era facile dimenticarsi dell'avvertenza quando ti capitava uno di quei casi in cui non controlli l'ordine di chiamata e di uso, che erano una minoranza, e il problema saltava fuori.

Avevo anche proposto per non cambiare tutto il codice che la funzione usasse ciclicamente una decina di array, mitigando il problema della non rientranza (ma comunque non risolvendolo alla radice; per risolverlo bisogna fare come dici tu: più scomodo ma sicuro).

Insomma... complimenti per lo stile. iOi

(*) non usavamo %f e compagnia perché i numeri andavano scritti con certi arrotondamenti "personalizzati" che solo questa funzione sapeva fare.
Big fan of ƎlectroYou!       Ausili per disabili e anziani su ƎlectroYou
Caratteri utili: À È É Ì Ò Ó Ù α β γ δ ε η θ λ μ π ρ σ τ φ ω Ω º ª ² ³ √ ∛ ∜ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ∃ ∄ ∆ ∈ ∉ ± ∓ ∾ ≃ ≈ ≠ ≤ ≥
Avatar utente
Foto UtenteGuidoB
17,8k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 2809
Iscritto il: 3 mar 2011, 16:48
Località: Madrid

1
voti

[8] Re: puntatori ed array

Messaggioda Foto UtenteDirtyDeeds » 3 ott 2013, 15:45

GuidoB ha scritto:Comunque sono d'accordo, è tirare il C oltre il limite delle intenzioni della classe static


Oltre le intenzioni direi di no perché alcune funzioni della libreria standard, sebbene ora deprecate, sono state scritte utilizzando questo "trucco".

Volendo, ci sarebbe un altro trucco con cui è possibile ritornare un (piccolo) array per valore, ed è quello di inglobare un array in una struct, p.es:

Codice: Seleziona tutto
typedef struct {
int val[5];
} Array;

Array DoSomething(void)
{
Array a = {.val = {1,2,3,4,5}};

// Un po' di codice

return a;
}


It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

0
voti

[9] Re: puntatori ed array

Messaggioda Foto UtenteMarcRider » 3 ott 2013, 18:07

fighissimo e figherrimo! :mrgreen:
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

1
voti

[10] Re: puntatori ed array

Messaggioda Foto UtenteTardoFreak » 3 ott 2013, 18:10

Formalmente si, ma se lo implementi su un micro non è una bellissima soluzione perché ritorni un' array, quindi un bel po' di bytes.
Passando il puntatore è meglio, molto meglio. E' più veloce, e risparmi memoria.
Codice: Seleziona tutto
#define DIM_MATRICE 3000

char miaMatrice[DIM_MATRICE];

void lavora_matrice(char *m, int dim)
{
  char valore;
 
  // punto al quarto elemento
  valore = *(m + 3);
 
}

void main(void)
{
  lavora_matrice(&miaMatrice,DIM_MATRICE);
}


In questo caso lavori su una matrice di ben 3000 bytes senza avere bisogno di uno stack mostruoso per ritornarla come risultato.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 0 ospiti