Newsgroup: it.hobby.elettronica.digitale
Titolo: ANSI C & CCS

Salve a tutti, ho un problema che mi attanaglia l'esistenza: sto
realizzando un programma in c destinato a girare su un pic, e mi sono
incagliato su  quelle che sono delle semplici routine che non vogliono
saperne di funzionare come voglio io, per spiegarmi meglio posto qui
sotto i vari spezzoni dei 2 metodi che danno problemi:
Questa routine riceve come parametro un int a 8 bit e lo trasforma in
un array di caratteri (tm[])
char bin8_toBCD(int n)
{char tmp[]="  0\0";       //predefinisco la stringa di out
...
...
return (tmp);//ritorna l'indirizzo del mio array bcd formato da
caratteri
}
Questa routine riceve un array di caratteri e provvede a inviare un
carattere alla volta al metodo lcd_putc() che provvede a stamparle su
un display il quale restituisce un true se si accorge che la stringa
e' finita( identifica il \0 ) fermando cosi' il ciclo while.
void lcd_print_string(char s[])
   {
   while ( !lcd_putc(*(s)) ) s++;
   }
Da main, ho scritto un paio di righe di test per verificare il
funzionamento:
...
char main_msg[]="Main menu\0";
...
void main()
{
char t[];
 lcd_print_string(main_msg);
 lcd_print_string(bin8_toBCD(234));
}
Accade che puntualmente il messaggio "Main menu" contenuto nella
variabile main_msg viene stampato regolarmente mentre il numero 234
che converto in bcd come caratteri memorizzato prima in tmp[], e
passato quindi al metodo  lcd_print_string non ne vuole sapere di
funzionare correttamente.
Il pasticcio succede quando chiamo  lcd_print_string fornendo t come
parametro: debuggando ho visto che appena entro in lcd_print_string il
parametro s[] contiene giustamente l'indirizzo di tmp e alla prima
chiamata lcd_putc(*(s)) il numero 2 viene stampato correttamente pero'
osservando la memoria vedo che il numero 234 e' gia' diventato 224 ho
avuto quindi una corruzione del dato.Sono io che sbaglio (magari
abituato troppo bene on java) o puo' essere un bug del compilatore che
non riserva quei 4 byte di memoria rendendoli disponibili ad altre
variabili che non centrano nulla?
Oltre alla probabile soluzione(non ho provato) di definire una
variabile di tipo char[] "visibile" per questi 3 metodi, posso
risolvere il problema in qualche altro modo?
(uso ccs pic ver. 4.018 (ansi c compiler) )
Grazie a tutti,
Enrico

 }
Nella variabile "t" definita all'interno del main deve essere definita la
dimensione dell'array. Inoltre non è mai utlizzata, quindi da eliminare.
La funzione bin8_toBCD ritorna un "char" non un "char *" che la funzione
lcd_print_string vuole come argomento.
Un consiglio: presta attenzione ai warning del compilatore (ovviamente devi
impostare il compilatore perchè te li fornisca in output).

    }
un modo più semplice, più veloce, e che ti fa risparmiare codice è fare 
così:
while (*s)
	lcd_putc(*s++);
Che risparmia il codice di controllo del \0 all'interno della lcd_putc.
Ciao

Non vi nascondo che io aggiungevo \0 non sapendo che di default il
compilatore lo aggiungesse in automatico una volta definita la
stringa.
Come si chiedeva Marco, nella conversione da int a bcd, definisco una
stringa tmp formata da 2 spazi uno zero e un carattere nullo finale:
una routine interna al metodo di conversione bcd, scansiona tre
variabili int(centinaia, decine, unita') del bcd appena creato e se
vede che prima del primo numero significativo ci sono zeri, nel array
tmp non fa nulla, lasciando gli spazi, altrimenti va a sovrascrivere
lo spazio con il numero corrispondente.Quando xro' passo uno zero da
convertire in bcd questa routine non fa niente finche' non trova il
carattere nullo alla fine, e se non avessi scritto uno zero
all'interno della stringa tmp in uscita avrei solamente un array con 3
spazi, quando invecie gradirei che venga mostrato uno zero.Ho
preferito fare cosi' xche' comunque dovevo definire tmp all'iniizo; mi
sembrava la soluzione + semplice per non aggiungere altro codice
.
Francesco dice che se scrivo cosi'
while (*s)
        lcd_putc(*s++);
risparmio codice: dunque io sapevo che il while accetta condizioni
vere o false: scritto cosi' sembra quasi che la condizione x cui il
ciclo while venga eseguito sia che *s diverso da zero! (effettivamente
pensandoci se tra() ho falso non fa il ciclo e quando ho un qualcosa
che non e' falso automaticamente (dovrebbe) essere vera, e quindi
esegui il ciclo: ma questa cosa vale x titti i programmi di
programmazione o solo nel c?).
Francamente non avrei mai creduto che una cosa del genere potesse
funzionare, e' per questo che facevo ritornare al metodo chiamante un
boolean.... comunque seguiro' il tuo consiglio visto che risparmiare
codice e' sempre una bella cosa sopratutto se hai a disposizione pochi
Kb x scrivere il programma
Ringrazio tutti per le risposte / consigli; a breve provero' ad
implementare i vostri suggerimenti.
Enrico

 ciclo while venga eseguito sia che *s diverso da zero!
Infatti è proprio quello che fa: fino a che il valore della cella puntata da
s è diverso da zero (condizione vera) esegue il corpo del ciclo, altrimenti
significa che hai incontrato il terminatore (condizione falsa)  
Ciao!
Marco / iw2nzm

 ciclo while venga eseguito sia che *s diverso da zero!
In ANSI C, il tipo booleano non esiste (č stato aggiunto dopo, nel c99 
mi sembra), i valori true/false sono cosě interpretati:
0 = false
diverso da 0 = vero
Tutti i confronti e le operazioni logiche, alla fine, ritornano un 
valore che puň essere valutato.
Anche se scrivi
(a > 5)
essa ritorna un valore, che puň essere assegnato, anche a un intero.
Sembra strano ma č proprio cosě, l'unica cosa a cui bisogna stare 
attenti č che se false = 0, sul true non possiamo fare assunzioni. 
Qualunque valore != da 0 viene interpretato come true.
Ciao