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

Tablica przesunięcia bitowe

xamrex 23 Lip 2011 13:58 2612 18
  • #1 9749569
    xamrex
    Poziom 28  
    Witam,
    Mam problem, bawię się już dłuższy czas i nie mogę sobie poradzić
    Dam 50 pkt za rozwiązanie problemu
    Chciałbym się dowiedzieć dlaczego korzystając z takiego polecenia
    test2=(tabela4[0]<<-1); // zwraca 9 CZEMU??

    Dostaję 9 zamiast 4


    taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod





    Próbowałem również tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    I dalej lipa, tak jakby nie mogę przypisywać wartości do zmiennych ;/
    Wiem że nie powinno się usuwać przesunięć bitowych ujemnych i powinienem zapisać to tak:

    test3=(tabela4[0]>>1);
    I nie byłoby problemu(o dziwo), ale ja akurat muszę użyć przesunięcia z liczbą ujemną.
    Nie wiem tylko czemu nie chce mi to zadziałać przy wyciąganiu z tablicy.
    Bardzo proszę o pomoc.
  • Pomocny post
    #2 9749952
    MarcinKawka
    Poziom 12  
    Napisz z jakiego kompilatora korzystasz i na jakim poziomie optymalizacji kodu wynikowego.

    Jeśli chodzi o standardy C to ISO99 mówi o ujemnym przesunięciu bitowym " the behavior is undefined" i właśnie dlatego lepiej unikać takich operacji.

    Jeśli koniecznie musisz być przygotowany na ujemne przesunięcia może utwórz własną funkcję:


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jeśli wywołanie dodatkowej funkcji jest dla ciebie nadmiernym balastem zrób z niej inlajn
  • #3 9749990
    tadzik85
    Poziom 38  
    <<-1 ?? co to za twór?
  • #4 9750010
    xamrex
    Poziom 28  
    Dzięki, fajny pomysł :D
    Jak nie będzie innych pomysłów to dostaniesz 50 pkt ode mnie :)
  • Pomocny post
    #5 9750024
    tadzik85
    Poziom 38  
    A no nie będzie. Parametrem operatora << lub >> może być tylko liczna naturalna.

    A przesunięcie o -1 bit to w ogóle sensu logicznego nie posiada. Bo co ma znaczyć?
  • #6 9750128
    xamrex
    Poziom 28  
    Ok, punkty przesłałem.
    Mam jeszcze pytanko odnośnie tego inline.
    Jeśli odpalę debuggera to czas wykonywania się tej funkcji jest taki sam z volatile jak i bez.
    Czy to oznacza, że nie nie ma potrzeby dodawać tego słówka, bo kompilator i tak się do niego nie stosuje, czy może lepiej dodać?

    Dodano po 1 [minuty]:

    tadzik85 napisał:
    A przesunięcie o -1 bit to w ogóle sensu logicznego nie posiada. Bo co ma znaczyć?


    Ja sobie napisałem tak "z głupot"
    test1=9<<-1; // zwraca poprawnie 4 (jest to rownowazne z test1=9>>1

    I okazało się to równoważne z 9>>1, więc pomyślałem, że może jest coś takiego :D (wiem głupio pomyślałem) i stąd te całe zamieszanie :)
  • #7 9750184
    tadzik85
    Poziom 38  
    A co wspólnego ma inline z volatile? nic

    inline jest tylko wskazówką dla kompilatora.
  • #8 9750213
    xamrex
    Poziom 28  
    tadzik85 napisał:
    A co wspólnego ma inline z volatile? nic

    To była literówka, oczywiście chodziło mi o inline.

    A więc jeśli przy debuggowaniu czasy wykonywania funkcji (z inline i bez inline) były takie same, to znaczy, że kompilator nie wziął tego pod uwagę nie ma sensu stosować inline?
  • #9 9750243
    MarcinKawka
    Poziom 12  
    xamrex napisał:
    Ok, punkty przesłałem.
    Mam jeszcze pytanko odnośnie tego inline.
    Jeśli odpalę debuggera to czas wykonywania się tej funkcji jest taki sam z volatile jak i bez.


    Jeśli używasz debuggera to sprawdź kod assemblerowy, jeśli funkcja wywoływana jest callem to najprawdopodobniej kompilator zignorował twój inline. Aby wymusić spróbuj w pliku nagłówkowym .h zadeklarować inline:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #10 9750306
    xamrex
    Poziom 28  
    Dalej ten sam czas...


    Może kompilator jest na tyle mądry, że sam dodaje do tej funkcji inline (nawet jeśli ja tego nie robię)
  • #11 9750554
    gaskoin
    Poziom 38  
    Jest to bardzo możliwe bo da się tak zrobić żeby funkcje były inlineowane, ale żeby stwierdzić, że tak jest u Ciebie musiałbyś podać parametry kompilacji.
  • #12 9751120
    tmf
    VIP Zasłużony dla elektroda
    Tak, kompilator jest na tyle mądry, że wszystkie funkcje do pewnej długości są traktowane jako inline. Stąd też nie widzisz różnicy. Co nie znaczy, że należy to inline opuścić. Nie należy, gdyż to jak długie funkcje są automatycznie traktowane jako inline się zmienia, zmienia się także wraz z wersją kompilatora. A dobrą praktyką jest przekazywać kompilatorowi maksymalną ilość informacji.
  • #14 9752055
    xamrex
    Poziom 28  
    Dodałem static i czas dalej jest taki sam
    Zarówno ze static inline jak i samo inline jak i bez dyrektywy inline.

    Więc czego powinienem użyć przy tej funkcji:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Samego inline, czy static inline?
  • #15 9752113
    gaskoin
    Poziom 38  
    xamrex napisał:
    Dodałem static i czas dalej jest taki sam
    Zarówno ze static inline jak i samo inline jak i bez dyrektywy inline.


    Toć napisałem, że kompilator dodaje inline za Ciebie dlatego nie widzisz różnicy. Jak wyłączysz opcje kompilatora , żeby nie inlineował funkcji to różnicę zauważysz.

    Wystarczy samo inline dodać, nie wiem po co tu static, ale to może freddie wyjaśni.
  • #16 9752118
    tmf
    VIP Zasłużony dla elektroda
    A jakiej różnicy się spodziewasz? Zajrzyj do pliku lss i zobacz jak kompilator wygenerował kod assemblerowy. Ta funkcja po prostu jest inlinowana z natury.
    static o którym pisze Freddie Chopin, spowoduje, że kompilator nie będzie generował kodu funkcji niezależnie od tego czy ją inlinuje, czy nie. Powoduje to zaoszczędzenie pewnej ilości miejsca. Szerzej masz to omówione w linku poniżej.
  • #17 9752342
    michalko12
    Specjalista - Mikrokontrolery
    gaskoin napisał:
    nie wiem po co tu static



    Bez static funkcja jest globalna. Na etapie kompilacji kompilator nie wie czy ta funkcja nie jest jeszcze gdzieś wykorzystywana i musi ja zostawić jako zwykłą funkcję dla linkera. Jeśli dasz static funkcja staje się lokalna i kompilator może ją wstawiać jako inline.
    Żeby funkcja static inline była globalnie widoczna trzeba ją całą umieścić w nagłówku.
    Bez static funkcja też może być wstawiana inline, ale i tak pozostanie wygenerowana wersja do wywołania. Wszystko zależy od od opcji optymalizacji kompilatora.
  • #18 9752729
    mirekk36
    Poziom 42  
    Przykład jak to sobie w prosty sposób sprawdzić korzystając z pliku *.lss

    mamy taki kod z funkcją inline:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    optymalizacja - pierwszy poziom -O1

    i w takiej postaci w pliku *.lss, w asemblerze kod pomiędzy sei a cli wygląda tak: (oczywiście to sei() i cli() to tylko tak żeby łatwiej zobaczyć fragment wywołania funkcji)


    Kod: text
    Zaloguj się, aby zobaczyć kod



    natomiast gdy wywalimy inline:


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    no to już masz w asemblerze ładny skok do funkcji call:


    Kod: text
    Zaloguj się, aby zobaczyć kod



    sprawdź sam u siebie

    bo przy włączonej optymalizacji -Os zawsze kod w asemblerze czy funkcja jest z inline czy bez wygląda tak samo (po mocnej optymalizacji) z czego należy się tylko cieszyć, bo widać że kompilator napisali łebscy ludzie:


    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #19 9753095
    xamrex
    Poziom 28  
    OK, dzięki za wszystkie informacje.
    Temat uważam za wyjaśniony i go zamykam.
    Dzięki jeszcze raz za wyjaśnienia
REKLAMA