An0nym8us Temat założony przez niniejszego użytkownika |
Przesunięcia bitowe - problem z utratą bitów » 2014-08-08 17:50:29 Witam, mam w zamiarze napisać prostą funkcję konwertującą VarInt do int. W tym celu postanowiłem wykorzystać przesunięcia bitowe, aby utracić 7 pierwszych niepotrzebnych bitów. Niestety, nie działają one w tej sytuacji: unsigned char ttt = 2u;
int result = (ttt << 7) >> 7; std::cout << result;
Natomiast działają w takiej: unsigned char ttt = 2u; ttt = ttt << 7; ttt = ttt >> 7; std::cout << (int)ttt;
I tutaj moje pytanie: dlaczego tak się dzieje? Czy program przechowuje w buforze rzekomo utracone bajty do czasu nadpisania danej zmiennej (w tym przypadku result)? PS: Proszę się nie sugerować nazwami zmiennych, wprowadzam byle jakie tylko wtedy kiedy coś "na szybko" testuję :). |
|
1234Marcineq |
» 2014-08-08 18:37:39 dzieje się tak bo int jest 32 bitowe int result = (ttt << 7) >> 7; powoduje że najpierw zmienna result ma wartość 256 binarnie wygląda to tak: 00000000 00000000 00000001 00000000 ( pierwsze przesunięcie te w nawiasie) drugie przesuniecie te poza nawiasem ustawia result spowrotem na 2 00000000 00000000 00000000 00000010
w drugim przypadku zmienne są 8-bitowe czyli w pierwszym przesunięciu jedynka wypada poza zmienną i nie wraca już w drugim. dlatego zmienna ma wartość 0.
|
|
An0nym8us Temat założony przez niniejszego użytkownika |
» 2014-08-08 23:52:59 Ok, ale czy tak działa kaskadowość operatorów? Poza tym, czy ta kaskadowość nie powinna "iść" od średnika, że się tak wyrażę ;-;? Czy po prostu kompilator wiedząc że wynik danych obliczeń znajdzie swój koniec w zmiennej typu int, tworzy w pamięci takową zmienną, na niej wykonuje te obliczenia a potem po prostu nadpisuje wskaźnik danego obiektu? Pytam bo z reguły nie wystarczy mi ogólna odpowiedź :). |
|
libed |
» 2014-08-09 01:22:09 Jesli interesuje Cie tylko pierwszy bit to zastosuj koniunkcje. int result = ttt & 1;[ / cpp ] |
|
Monika90 |
» 2014-08-09 09:11:06 Co to jest kaskadowość operatorów idąca od średnika?
Całkowitoliczbowe argumenty operatorów arytmetycznych (+ - * << >> itp) przed wykonaniem działania są poddawane promocji całkowitoliczbowej. Tzn, "małe" typy (między innymi bool, char, signed char, unsigned char, short, signed short) są konwertowane na int (na ogół na int), większe promocja pozostawia bez zmian. Te większe też mogą być konwertowane, ale to juz nie będzie promocja, to będzie zwykła konwersja arytmetyczna.
Zatem, jezeli mamy coś takiego
unsigned char x = 2; x = x << 7;
to najpierw zostanie utworzona tymczasowa wartośc 2 typu int. Następnie zostanie przesunięta o 7 pozyji w lewo, wynikiem czego będzie 256 typu int. 256 będzie przypisane do zmiennej typu unsigned char, co polega na odrzuceniu nadmiarowych bitów, więc do x będzie przypisane 0. |
|
An0nym8us Temat założony przez niniejszego użytkownika |
» 2014-08-09 14:56:59 Pisząc "kaskadowość operatorów idąca od średnika" miałem na myśli: int x, y, z; x = y + z + x;
Wg mojego rozumowania (i tego co "chyba" widziałem w poradnikach) pierwsze wykona się "z + x" (wynik nazwijmy "result"), następnie "y + result", a potem wynik zostanie przypisany do 'z' poprzez operator '='. Niemniej - dzięki za wyjaśnienie, teraz już to rozumiem :D. |
|
Monika90 |
» 2014-08-09 16:04:18 x = x + y + z; to jest to samo co x = ((x + y) + z); może to zostać obliczone dowolnie, byle by wynik i wszystkie obserwowalne efekty uboczne były takie jakby najpierw było obliczone pierwsze dodawanie (od lewej), potem drugie i na końcu przypisanie do x.
Przy czym, pomimo tego że kolejność wykonywania dodawań jest tutaj określona, to kolejność wartościowania podwyrażeń x, y i z nie jest. Gdyby za x, y i z podstawić wywołania funkcji: f() + g() + h() to nie wiadomo w jakiej kolejności względem siebie byłyby te funkcje wywołane. |
|
An0nym8us Temat założony przez niniejszego użytkownika |
» 2014-08-14 13:41:59 Ok, mój kod aktualnie działa :). Dzięki za pomoc, pozdrawiam :). |
|
« 1 » |