logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8] [c] Dziwne zachowanie atmegi w if'ie

y0yster 18 Gru 2008 11:31 1416 8
  • #1 5872728
    y0yster
    Poziom 19  
    Witam.

    Ostatnio zauważyłem pisząc program pod Atmega8, że przy instrukcji warunkowej (if) program mi wariuje.

    Dzieje się to wtedy, gdy w warunku podaję jakąś operację arytmetyczną, wtedy program wogóle nie wykonuje takiego warunku. Czy to oznacza, że nie jest to wspierane. Rozwiązałem ten problem przez stworzenie zmiennej lokalnej, ale nie jest to rozwiązanie na dłuższą metę.

    Co proponujecie?

    Pozdrawiam.
  • #2 5872848
    shadow0013
    Poziom 34  
    Bez podania jaki to język i zamieszczenia fragmentu kodu raczej nikt Ci nie pomoże.
  • #3 5873201
    vcd_a
    Poziom 18  
    Hmmm jak na razie to pewnie nic nikt nie wie o co Ci chodzi ;p, pokaż kawałek kodu, pozdrawiam Krzysiek

    P.S. Próbowałeś zmiennych z "volatile"?
  • #4 5873427
    mirekk36
    Poziom 42  
    shadow0013 -> autor podał jaki to język - widać w tagach tematu, że to język C

    .... ale pytanie jest tak mocno wyrwane z kontekstu, że i tak ciężko coś podpowiedzieć, więc na pewno przydałby się kawałek kodu - przez który to tak "wariuje" - może się wtedy okazać, że coś źle robisz - zamiast odrazu przypuszczać, że kompilator czegoś tam nie wspiera ;)
  • #5 5873639
    y0yster
    Poziom 19  
    
    
    [...]
    case 3:
    {
    
    	char badaj = animacja + plus_minus;
    
    	if( badaj == 0)
    
    [...]
    }
    
    


    Ten kawałeczek kodu jest w 2 pętlach i 2 if'ach. A jak widać jeszcze do tego jest blok switch case.

    Chciałbym, żeby to wyglądało tak:

    
    
    [...]
    case 3:
    {
    
    	//char badaj = animacja + plus_minus;
    
    	if( animacja + plus_minus == 0)
    
    [...]
    }
    
    


    Próbowałem dawać w nawiasy to wyrażenie chociaż nie ma to głębszego sensu, mimo wszystko nic to nie daje.

    if( (animacja + plus_minus) == 0)

    Pozdrawiam.
  • #6 5873671
    dawid512
    Poziom 32  
    A co jeżeli któraś ze zmiennych podana w warunku zmienia swoją wartość podczas jego sprawdzania? Warunek nigdy nie będzie spełniony. Po za tym wydaje mi się że lepiej byłoby najpierw wykonać operacje matematyczną i zapisać jej wynik do zmiennej a następnie porównać ją w warunku z inną. Lecz to tylko moje zdanie.
  • #7 5873721
    BoskiDialer
    Poziom 34  
    y0yster: Pokaż jakiego typu są zmienne "animacja" oraz "plus_minus". Jeśli wynik najpierw wpisujesz do zmiennej typu char, to sprawdzasz, czy dolne 8 bitów jest wyzerowane. Jeśli jednak robisz porównanie bez wykorzystania zmiennej "badaj", bez rzutowania typów, bez maskowania bitów, to może się okazać, że dolne 8 bitów jest wyzerowane, ale wynik dodawania ma 2 lub więcej bajtów, powyżej dolnego bajtu jest różny od zera (warunek nie spełniony, kiedy być powinien). Tak więc oba warunki są różne!

    Sprawdź to:
    if( (char)(animacja + plus_minus) == 0)
    // lub:
    if( ((animacja + plus_minus) & 0xFF) == 0)
  • #8 5873845
    y0yster
    Poziom 19  
    dawid512 napisał:
    A co jeżeli któraś ze zmiennych podana w warunku zmienia swoją wartość podczas jego sprawdzania? Warunek nigdy nie będzie spełniony. Po za tym wydaje mi się że lepiej byłoby najpierw wykonać operacje matematyczną i zapisać jej wynik do zmiennej a następnie porównać ją w warunku z inną. Lecz to tylko moje zdanie.


    Właśnie tak robię.

    BoskiDialer napisał:
    y0yster: Pokaż jakiego typu są zmienne "animacja" oraz "plus_minus". Jeśli wynik najpierw wpisujesz do zmiennej typu char, to sprawdzasz, czy dolne 8 bitów jest wyzerowane. Jeśli jednak robisz porównanie bez wykorzystania zmiennej "badaj", bez rzutowania typów, bez maskowania bitów, to może się okazać, że dolne 8 bitów jest wyzerowane, ale wynik dodawania ma 2 lub więcej bajtów, powyżej dolnego bajtu jest różny od zera (warunek nie spełniony, kiedy być powinien). Tak więc oba warunki są różne!


    Obie zmienne są typu char. Z tym, że animacja jest deklarowana globalnie, a plus_minus jest deklarowana w jednym z bloków if, o którym wcześniej wspominałem i jeszcze w jednej pętli. Ale takie zagnieżdżenie nie powinno wpływać na działanie programu.

    Dodam, że operacja porównania jest wykonywana w funkcji, co także nie powinno wpływać na takie działanie.

    Jeszcze jedną istotną rzeczą jest to, że zmienna plus_minus przyjmuje wartości -1 lub 1 (i 0 tylko przy deklaracji) co może mieć większe znaczenie. Możliwe, że coś by się działo przy -1, ale to samo się dzieje dla 1, więc nie wiem.

    Pozdrawiam.
  • Pomocny post
    #9 5873915
    BoskiDialer
    Poziom 34  
    Sprawdziłem jak wygląda wygenerowany kod: owszem dwie zmienne char będą wczytane, ale do porównania są rzutowanie na typ int (2 bajty ze znakiem, bit znaku jest rozszerzany), przez co porównanie nie działa tak, jak powinno. Jawne rzutowanie z (char) które podałem spowodowało wygenerowanie poprawnego kodu.

    Kod testowy:
    	char c1;
    	char c2;
    	asm volatile("; c1:%0 c2:%1":"=r"(c1),"=r"(c2):);
    	if(c1 + c2 == 0)
    		asm volatile("/** IF:TRUE **/"::);
    wygenerowany kod z moimi komentarzami:
    	; c1:r18 c2:r24
    /* #NOAPP */
    	// rozszerzenie c2 o znak
    	clr r25
    	sbrc r24,7
    	com r25
    	// rozszerzenie c1 o znak
    	clr r19
    	sbrc r18,7
    	com r19
    	// dodanie do siebie liczb dwubajtowych
    	add r24,r18
    	adc r25,r19
    	// sprawdzenie, czy wynik jest równy zero
    	or r24,r25
    	brne .L6
    /* #APP */
    	/** IF:TRUE **/

    Kod testowy z rzutowaniem:
    	char c1;
    	char c2;
    	asm volatile("; c1:%0 c2:%1":"=r"(c1),"=r"(c2):);
    	if((char)(c1 + c2) == 0)
    		asm volatile("/** IF:TRUE **/"::);

    wynik:
    	; c1:r25 c2:r24
    /* #NOAPP */
    	add r24,r25
    	brne .L6
    /* #APP */
    	/** IF:TRUE **/
REKLAMA