bug w gcc??

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?

Reply to
Greg
Loading thread data ...

Greg napisał(a):

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.

Reply to
Wojtek Kaniewski

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 :)

Reply to
antek
Reply to
Greg(G.Kasprowicz

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ę.
Reply to
antek

Greg(G.Kasprowicz) przemówił ludzkim głosem:

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.

Reply to
Zbych

Dzieki za wyjasnienie, wszystko juz jasne. Pozdr

Reply to
Greg(G.Kasprowicz

jeszcze raz dzieki, wszystko teraz ladnie dziala, wlasnie sprawdzilem:)

Reply to
Greg

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.