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

(ATmega][C] Przesunięcie bitowe liczby int long

Myrek1 10 Kwi 2009 17:04 5045 4
  • #1 6397796
    Myrek1
    Poziom 23  
    Witam.
    Mam problem z przesunięciem bitowym. Mam taki kod:

    
    
    long int wire_temp(void)
    {
    long int zmienna_w;
    int temp1, temp2;
    
            temp1 = 0xCBCF;
            temp2 = 0xEBAA;
    	zmienna_w =  ((temp2 << 16) | temp1);
    
    return zmienna_w;
    }
    


    i wynik działania jest błędny. zamiast 0xEBAACBCF jest 0xFFFFCBCF. Widać, że dwa najstarsze bajty się nie przesuwają, zamiast tego wstawiane są tam FFFF. Dlaczego?
  • #2 6397899
    piti___
    Poziom 23  
    Witam
    musisz wcześniej rzutować temp2 na long int.

    zmienna_w = (((long int)temp2 << 16) | temp1);
  • #3 6399209
    Myrek1
    Poziom 23  
    Dzięki.
    A mógłbyś powiedzieć dlaczego tak akurat działa? Sam poradziłem sobie w inny sposób:

    
    	zmienna_w = temp2;
    	zmienna_w = zmienna_w <<16;
    


    Mam też inne pytanie. Mam oto liczbę float e
    FLoat zawiera liczbę z przedziału 0-1.
    Chciałbym zapisać jej cztery bajty w buforze.

    Mam coś takiego:

    
    uint8_t bufor[4]
    
        bufor[0]= ((long unsigned int)e & 0xFF000000)>>24;
        bufor[1]= ((long unsigned int)e & 0x00FF0000)>>16;
        bufor[2]= ((long unsigned int)e & 0x0000FF00)>>8;
        bufor[3]= (long unsigned int)e & 0x000000FF;
    
    


    No i nie działa. Jak można to inaczej zrobić? Czy dobrze rzutuje zmienne? Czy trzeba jeszcze rzutować całość (bufor[3]= (uint8_t)(long unsigned int)e & 0x000000FF;)?


    Kompilator to AVR-GCC.
    Dzięki.
  • #4 6399572
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Myrek1 napisał:
    A mógłbyś powiedzieć dlaczego tak akurat działa?

    Bo liczby wpisane na stałe do kodu mają domyślnie jakąś wielkość. Tą domyślną wielkością zawsze jest int, który dla AVR-GCC ma akurat 16-bitów. 16-bitowa liczba po przesunięciu jej o 16-pozycji będzie zawierać same zera.

    Cytat:
    Mam też inne pytanie. Mam oto liczbę float e
    [...]

    To co napisałeś powinno działać, jeśli nie działa, to możesz zrobić to inaczej, co zresztą jest o wiele lepszą opcją:

    bufor[i]=((uint8_t*)e)[i];

    Cytat:
    Czy trzeba jeszcze rzutować całość (bufor[3]= (uint8_t)(long unsigned int)e & 0x000000FF;)?

    1. Nie trzeba, przy przepisaniu kompilator sam dokona stosownej konwersji.
    2. W jednym miejscu stosujesz standardowe typy (long int), a winnym nowsze wersje (uint8_t) - zdecyduj się może na jedną wersję i się jej trzymaj.

    4\/3!!
  • #5 6399642
    Dr.Vee
    VIP Zasłużony dla elektroda
    Najlepiej wykonywać konwersję za pomocą unii:
    union {
        float flt;
        uint8_t u8[4];
    } temp;
    temp.flt = e;
    /* tutaj robisz co Ci się podoba z temp.u8 */

    Rzutowanie float na uint8_t* itp może być mniej efektywne + podpada pod aliasing wskaźników.

    Pozdrawiam,
    Dr.Vee
REKLAMA