2016-06-14 39 views
6

Podczas sesji debugowania dowiedziałem się, że snprintf nie działa zgodnie z oczekiwaniami podczas łączenia kodu z avr-gcc. Przykładowy kod powinien po prostu przekształcić wartość zmiennoprzecinkową 3999.9f na swoją reprezentację znaku.Snprintf nie działa zgodnie z oczekiwaniami z avr-gcc

Oto minimalne sprawdzian:

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 kod przykład AVR GCC i prowadzenia go Atmel Studio 7 daje wartość powrotną -2. Oznacza to, że snprintf nie działa.

Co, jeśli próbowałeś do tej pory?

  • Testowałem kod na 32 i 64 Linux i działa zgodnie z oczekiwaniami (TestSnprintf zwraca wartość 0).
  • Przetestowałem kod za pomocą Visual Studio 2015 i działało zgodnie z oczekiwaniami (TestSnprintf zwraca wartość 0).
  • Zawartość buf jest

    buf[0] = 32;  
    buf[1] = 32;  
    buf[2] = 32;  
    buf[3] = 32;  
    buf[4] = 32;  
    buf[5] = 63;  
    buf[6] = 0; 
    
  • Próbę przeprowadza się w urządzeniu za pomocą interfejsu JTAG. Wypróbowałem także symulator, z tym samym wynikiem.

  • Brak optymalizacji kompilatora. Kod jest kompilowany i debugowany za pomocą -O0.

Oto zrzut ekranu z sesji debugowania, który pokazuje, że zwracana wartość to -2.

enter image description here

To pokazuje, że jest w zakresie buf podczas debugowania: enter image description here

pytań

Co robię źle?

ROZWIĄZANIE

Przede wszystkim dziękuję wszystkim bardzo za pomoc! Jak podkreślił @manilo następujące opcje łącznikowe brakowało:

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

Biblioteka standardowa C nie jest częścią gcc! Z której biblioteki korzystasz? – Olaf

+0

Powinieneś dowiedzieć się, co właściwie zawiera 'buf'. –

+1

Czy łączyłeś się z 'libm'? ('-lm') – fukanchik

Odpowiedz

9

Istnieją trzy różne implementacje printf() (i przyjaciół). Wartość domyślna nie implementuje danych wyjściowych typu float.

snprintf nie będzie działać bez powiązania libprintf_flt.a (-lprintf_flt) i libm.a (-lm).

Ponadto, zgodnie z dokumentacją, należy dodać opcje linkera: -Wl,-u,vfprintf (np. http://winavr.scienceprog.com/avr-gcc-tutorial/using-sprintf-function-for-float-numbers-in-avr-gcc.html).

Sekwencja flagi łącznikowych jest ważne: -Wl,-u,vfprintf -lprintf_flt -lm

+0

@manilo Wielkie dzięki, dodanie tych flag wykonało zadanie. – orbitcowboy

-1

„Należy również pamiętać, że domyślnie Arduino IDE nie ustawić opcje AVR łącznikowych do wsparcia zmiennoprzecinkowych w xxprintf() procedury Więc podczas gdy ratuje dość. trochę przestrzeni kodu na kompilacjach AVR, oznacza to, że funkcje printf() nie mogą być używane do wyprowadzania zmiennoprzecinkowego w AVR. Domyślnie dla innych procesorów jest włączona obsługa pływająca. " http://playground.arduino.cc/Main/Printf

+0

Używam programu Atmel Studio nie jako Arduino IDE. – orbitcowboy