Zagadkowe mnożenie w avr-gcc 3.4.5: problemy z U32 i stałą 10 000
bug w gcc??
From: "Greg" <Grzegorz.Kasprowicz_at_nospam_CERN.CH>
Subject: bug w gcc??
Date: Wed, 22 Mar 2006 17:28:57 +0100
Witam
walcze z gcc pod AVR (avr-gcc (GCC) 3.4.5), i chyba znalazlem buga
gdy mnoze liczbe zzakresu 0-9 (U8) przez stala 10 000, mnozenie dziala
poprawnie do rezultatu nie wiekszego niz 30 000. Zmienna jest typu U32, przy
unsigned integer, long jest tak samo. Dzialo by sie tak, gdybym zadeklarowal
ja jako U16, ale mam U32
wynik mnozenia dla wartosci wiekszych niz 3 jest : FFFFxxxx
Co ciekawe mnozenie * 100 000 dziala OK.
oto linsting przy ktorym sa takie jaja:
przetwarza on ciag liczb BCD pobranych z klawiatury (input_buffer) na 32bit
(input_frequency )
U32 input_frequency ;
input_frequency = 0;
input_frequency = input_buffer[6] + input_buffer[5] *10 +
input_buffer[4]*100 + input_buffer[3]*1000 + input_buffer[2]*10000
+input_buffer[1]*100000;
no i on nie dziala poprawnie
natomiast jak obejde problem mnozenia przez 10 000 tak:
U32 input_frequency ;
input_frequency = 0;
for (U8 nr=1; nr< (input_buffer[2]+1); nr++)
{
input_frequency+=10000;
}
input_frequency += input_buffer[6] + input_buffer[5] *10 +
input_buffer[4]*100 + input_buffer[3]*1000 + input_buffer[1]*100000;
to wszystko jest w porzadku
czy ja czegos nie rozumiem czy to bug?
From: =?iso-8859-2?Q?Piotr_Ga=B3ka?= <piotr.galka_at_nospam_CUTTHISmicromade.pl>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 17:55:43 +0100
Użytkownik "Greg" <Grzegorz.Kasprowicz_at_nospam_CERN.CH> napisał w wiadomości
news:dvru08$r73$1_at_nospam_sunnews.cern.ch...
Witam
walcze z gcc pod AVR (avr-gcc (GCC) 3.4.5), i chyba znalazlem buga
gdy mnoze liczbe zzakresu 0-9 (U8) przez stala 10 000, mnozenie dziala
poprawnie do rezultatu nie wiekszego niz 30 000. Zmienna jest typu U32,
przy unsigned integer, long jest tak samo. Dzialo by sie tak, gdybym
zadeklarowal ja jako U16, ale mam U32
wynik mnozenia dla wartosci wiekszych niz 3 jest : FFFFxxxx
Co ciekawe mnozenie * 100 000 dziala OK.
oto linsting przy ktorym sa takie jaja:
przetwarza on ciag liczb BCD pobranych z klawiatury (input_buffer) na
32bit (input_frequency )
U32 input_frequency ;
input_frequency = 0;
input_frequency = input_buffer[6] + input_buffer[5] *10 +
input_buffer[4]*100 + input_buffer[3]*1000 + input_buffer[2]*10000
+input_buffer[1]*100000;
W mnożeniu (tym przez 10000) żaden czynnik nie jest U32 więc o co chodzi ?
P.G.
From: "Greg" <Grzegorz.Kasprowicz_at_nospam_CERN.CH>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 18:11:42 +0100
W mnożeniu (tym przez 10000) żaden czynnik nie jest U32 więc o co chodzi ?
o to chodzi, ze jak pomnoze 3*10 000 to mam 30 000 (0x00007530)
ale jak pomnoze 5* 10 000, to mam jakies krzaki, np 0xFFFFF350 zamiast
0x0000C350 wraz ze swoimi konsekwencjami jak wyswietlam to na LCD
natomiast jak pomnoze 5 przez 100 000 to mam prawidlowo: 0x0007A120
dlatego musialem uzyc innego algorytmu z dodawaniem
co jest grane?
From: Wojtek Kaniewski <wojtekka_at_nospam_SPAM.SPAM.SPAM>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 18:28:31 +0100
Greg napisał(a):
o to chodzi, ze jak pomnoze 3*10 000 to mam 30 000 (0x00007530)
ale jak pomnoze 5* 10 000, to mam jakies krzaki, np 0xFFFFF350 zamiast
0x0000C350 wraz ze swoimi konsekwencjami jak wyswietlam to na LCD
natomiast jak pomnoze 5 przez 100 000 to mam prawidlowo: 0x0007A120
dlatego musialem uzyc innego algorytmu z dodawaniem
3, 5 i 10000 to dla avr-gcc stałe 16-bitowe i ich mnożenie daje wynik
16-bitowy. 100000 to stała 32-bitowa, więc wynik mnożenia z jej udziałem
jest 32-bitowy. żeby stała mniejsza od 65536 była traktowana jak
32-bitowa trzeba dodać na końcu ,,L'' dla stałej ze znakiem lub ,,UL''
dla stałej bez znaku. w Twoim przypadku powinno być mnożenie przez
10000L, nie 10000.
w.
From: antek <ten_at_nospam_adres.jest.be>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 19:08:21 +0100
3, 5 i 10000 to dla avr-gcc stałe 16-bitowe i ich mnożenie daje wynik
16-bitowy. 100000 to stała 32-bitowa, więc wynik mnożenia z jej udziałem
jest 32-bitowy. żeby stała mniejsza od 65536 była traktowana jak
32-bitowa trzeba dodać na końcu ,,L'' dla stałej ze znakiem lub ,,UL''
dla stałej bez znaku. w Twoim przypadku powinno być mnożenie przez
10000L, nie 10000.
Potwierdzam, ze 2h mi zajęło szukanie błędu w swoim programie jak w
jednej ze staluch zapomniałem dodać sobie przyrostka U. A przecież
wszystko to jest opisane w standardzie ANSI C jak byk :)
From: "Greg\(G.Kasprowicz\)" <gkasprow_at_nospam_gmail.com>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 21:52:48 +0100
3, 5 i 10000 to dla avr-gcc stałe 16-bitowe i ich mnożenie daje wynik
16-bitowy. 100000 to stała 32-bitowa, więc wynik mnożenia z jej udziałem
jest 32-bitowy. żeby stała mniejsza od 65536 była traktowana jak
32-bitowa trzeba dodać na końcu ,,L'' dla stałej ze znakiem lub ,,UL''
dla stałej bez znaku. w Twoim przypadku powinno być mnożenie przez
10000L, nie 10000.
Potwierdzam, ze 2h mi zajęło szukanie błędu w swoim programie jak w jednej
ze staluch zapomniałem dodać sobie przyrostka U. A przecież wszystko to
jest opisane w standardzie ANSI C jak byk :)
Dzieki wielkie, jutro przetestuje
ale nie daje mi spokoju to, ze przeciez zadeklarowalem zmienna 32 bit i
dodawalem do niej 16 bit, wiec skad te FFFF sie wziely?
dlaczego dodawanie zmiennej n* 1000 nie powodowalo takich problemow?
tylko te n*10000
czy tylko przypadkiem dla mneijszych liczb tak mi wyszlo, ze w pamieci byly
zera zamiast 2 najstarszych bajow i kompilator potraktowal ja jak ozmienna
32bit?
Tak czy inaczej dzieki!
From: antek <ten_at_nospam_adres.jest.be>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 22:11:02 +0100
Dzieki wielkie, jutro przetestuje
ale nie daje mi spokoju to, ze przeciez zadeklarowalem zmienna 32 bit i
dodawalem do niej 16 bit, wiec skad te FFFF sie wziely?
dlaczego dodawanie zmiennej n* 1000 nie powodowalo takich problemow?
tylko te n*10000
10000 mieści się jeszcze w typie int ze znakiem. Zauważ, że działa
dobrze do 30000, bo następny wynik, 40000 przekracza już dopuszczalny
rozmiar dla typu signed int. Dla 100000 jest też ok bo tu już przy
mnożeniu nawet przez 9 nie przekracza się zakresu dla zmiennej zarówno
signed jak i unsigned long. Jak proponowal przedpiśca przyrostek L a
nawet dla pewności UL załatwi sprawę.
From: "Greg\(G.Kasprowicz\)" <gkasprow_at_nospam_gmail.com>
Subject: Re: bug w gcc??
Date: Thu, 23 Mar 2006 01:01:58 +0100
Dzieki za wyjasnienie, wszystko juz jasne.
Pozdr
From: "Greg" <Grzegorz.Kasprowicz_at_nospam_CERN.CH>
Subject: Re: bug w gcc??
Date: Thu, 23 Mar 2006 10:52:17 +0100
jeszcze raz dzieki, wszystko teraz ladnie dziala, wlasnie sprawdzilem:)
From: Zbych <abuse_at_nospam_onet.pl>
Subject: Re: bug w gcc??
Date: Wed, 22 Mar 2006 22:21:13 +0100
Greg(G.Kasprowicz) przemówił ludzkim głosem:
ale nie daje mi spokoju to, ze przeciez zadeklarowalem zmienna 32 bit i
dodawalem do niej 16 bit, wiec skad te FFFF sie wziely?
Ano stąd, że zmienna 16-bitowa była ze znakiem, a rzutowanie 16-bit ze
znakiem na 32 bez znaku powoduje w gcc ekspansję ze znakiem (czyli
najstarszy bit zmiennej 16-bit jest powielany na dwa najstarsze bajty
zmiennej 32-bit).
Wklep sobie coś takiego i sprawdź kod wynikowy:
volatile uint32_t a;
volatile int16_t b;
b=-15000;
a=b;
Z tego co pamiętam to ansi c nie specyfikuje, co powinno się stać ze
znakiem przy konwersji signed->unsigned, więc w różnych kompilatorach
może być różnie.