2016-06-14 18 views
6

Durante una sessione di debug, ho scoperto che snprintf non funziona come previsto quando si comilla il codice con avr-gcc. Il codice di esempio dovrebbe semplicemente convertire il valore in virgola mobile 3999.9f nella sua rappresentazione di carattere.snprintf non funziona come previsto con avr-gcc

Qui è un banco di prova minima:

int TestSnprintf(void) 
    { 
     const float inputValue = 3999.9f; 
     /* Print with a fixed width of 6 characters (5 numbers and 1 dot). 
     The buffer must have a length of 7, because snprintf appends a '\0' at the end. */ 
     char buf[7U] = {0, 0, 0, 0, 0, 0, 0}; 
     const uint8_t bufferSize = 7U; 
     if(6 != snprintf(buf, bufferSize, "%06.1f", inputValue)) 
     { 
      return -1; 
     } 
     if(buf[0] != '3' 
      || buf[1] != '9' 
      || buf[2] != '9' 
      || buf[3] != '9' 
      || buf[4] != '.' 
      || buf[5] != '9' 
      || buf[6] != '\0') 
     { 
      return -2; 
     } 

     return 0; 
    } 

    int main(void) 
    { 
    int retVal = TestSnprintf(); 
    return 0; 
    } 

compling questo codice di esempio con avr-gcc e funzionante con Atmel Studio 7 dà un valore di ritorno di -2. Ciò significa che snprintf non funziona.

E se avessi provato fino ad ora?

  • Ho testato il codice su 32 e 64 Linux e funziona come previsto (TestSnprintf restituisce il valore 0).
  • Ho testato il codice con Visual Studio 2015 e ha funzionato come previsto (TestSnprintf restituisce il valore 0).
  • Il contenuto di buf è

    buf[0] = 32;  
    buf[1] = 32;  
    buf[2] = 32;  
    buf[3] = 32;  
    buf[4] = 32;  
    buf[5] = 63;  
    buf[6] = 0; 
    
  • La prova viene eseguita sul dispositivo tramite l'interfaccia JTAG. Ho provato anche il simulatore, con lo stesso risultato.

  • Non è attivata l'ottimizzazione del compilatore. Il codice è compilato e sottoposto a debug con -O0.

Ecco uno screenshot della sessione di debug, che dimostra che il valore di ritorno è -2.

enter image description here

Ciò dimostra che buf è portata durante il debug: enter image description here

Domanda

quello che sto facendo di sbagliato?

SOLUZIONE

Prima di tutto grazie a tutti molto per il vostro aiuto! Come ha sottolineato @manilo le seguenti opzioni di linker mancavano:

-Wl,-u,vfprintf -lprintf_flt -lm 
+0

E la libreria C standard non fa parte di gcc! Quale libreria usi? – Olaf

+0

Dovresti scoprire cosa contiene effettivamente "buf". –

+1

Ti sei collegato con 'libm'? ('-lm') – fukanchik

risposta

9

Ci sono tre diverse implementazioni di printf() (e amici). L'impostazione predefinita non implementa l'output float.

snprintf non funziona senza collegamento libprintf_flt.a (-lprintf_flt) e libm.a (-lm).

Inoltre, in base alla documentazione, è necessario aggiungere le opzioni del linker -Wl,-u,vfprintf (ad esempio http://winavr.scienceprog.com/avr-gcc-tutorial/using-sprintf-function-for-float-numbers-in-avr-gcc.html).

La sequenza delle bandiere linker è importante: -Wl,-u,vfprintf -lprintf_flt -lm

+0

@manilo Mille grazie, l'aggiunta di queste bandiere ha funzionato. – orbitcowboy

-1

"Si noti inoltre che per default l'IDE Arduino non imposta le opzioni AVR linker per sostenere in virgola mobile nel xxprintf() routine Così, mentre che salva tutto. un po 'di spazio del codice sui build AVR, significa che le funzioni printf() non possono essere utilizzate per l'output in virgola mobile sull'AVR. Il supporto flottante è incluso di default per gli altri processori. " http://playground.arduino.cc/Main/Printf

+0

Utilizzo Atmel Studio non un IDE Arduino. – orbitcowboy

Problemi correlati