Bytearray schieben



  • Das sieht vielversprechend aus.

    Ich muss ja noch herrausfinden wie viele bits mein Array verschoben ist, ich hab mir da folgendes überlegt, leider funktioniert es nicht:

    // Die einträge von "bytes" sind unsigned shorts, also bereits 16 bit
    		for(int offset = 0; offset < 20; offset++)
    		{
    			if(0x0001 == (bytes[0] << offset) || (bytes[1] >> (16-offset))) break;
    		}
    

    compiler sagt:

    error C2678: Binärer Operator '<<': Es konnte kein Operator gefunden werden,
    


  • template<typename T,
             std::size_t N>
    void rshift_arr( T(&arr)[N], std::size_t to_shift )
    {
        auto bytes = reinterpret_cast<unsigned char*>(arr);
        auto index = N * sizeof(T);
        while( index-- )
        {
            bytes[index] >>= to_shift;
    
            if( index )
                bytes[index] |= (bytes[index - 1] << (CHAR_BIT - to_shift));
        }
    }
    

    Worst Code ever!
    1. Gaukelt vor, ein Template zu sein, aber alles was es mit den Typen macht ist nur ein reinterpret_cast<unsigned char*> (lol).
    2. Geht nur für Arrays, dessen Länge zur Compile-Time feststeht
    3. Es ist nicht klar, weshalb size_t, das legt nahe, to_shift könne beliebig gross sein (aber warum nicht negativ? Ein memmove reicht um to_shift zwischen 0 und CHAR_BIT zu bringen)
    4. Sehr wirre Art, eine for-Loop zu schreiben
    5. Ein sehr ineffiziente Art, eine for-Loop zu schreiben



  • Sone schrieb:

    Nein, die Lösung funktioniert nur solange das Array von der Gesamtgröße her nicht größer ist als ein Skalar.

    cl90 schrieb:

    Also es gehören immer 4 Bytes zusammen,[...]

    😕


  • Mod

    Denkt da dran, dass ein Shift einer 4-Byte Zahl ganz ein anderes Ergebnis haben kann als ein Shift von 4 Mal einem Byte. Endianess und so.



  • Worst argumentation ever!

    1. Gaukelt vor, ein Template zu sein, aber alles was es mit den Typen macht ist nur ein reinterpret_cast<unsigned char*> (lol).

    Kann man natürlich umschreiben, das war nur der Bequemlichkeit des Beispiels wegen.

    2. Geht nur für Arrays, dessen Länge zur Compile-Time feststeht

    Nein, die Lösung lässt sich sehr leicht anpassen, s.o.

    3. Es ist nicht klar, weshalb size_t, das legt nahe, to_shift könne beliebig gross sein

    Nein, könnte es nicht. Es macht keinen Sinn.

    aber warum nicht negativ?

    Weil es so nicht geht. Das Prinzip lässt sich nicht mit einer negativen shift-Breite in einen links-Shift umwandeln, deswegen heißt es explizit rshift.
    Btw, man merkt, was für eine Sorte du bist:

    N3690 §5.8/1 schrieb:

    The behavior is undefined if the right operand
    is negative

    Ein memmove reicht um to_shift zwischen 0 und CHAR_BIT zu bringen

    😕

    4. Sehr wirre Art, eine for-Loop zu schreiben

    Geschmackssache. Zeig mir, wie du es schöner machst - nicht einfach anders.

    5. Ein sehr ineffiziente Art, eine for-Loop zu schreiben

    So? Schreibe dieselbe for-loop um und zeige mir, dass es effizienter ist.
    Klar, man könnte

    while( index-- )
        {
            bytes[index] >>= to_shift;
    
            if( index )
                bytes[index] |= (bytes[index - 1] << (CHAR_BIT - to_shift));
        }
    

    Umschreiben zu

    while( index-- > 1 )
        {
            bytes[index] >>= to_shift;
            bytes[index] |= (bytes[index - 1] << (CHAR_BIT - to_shift));
        }
    
        bytes[0] >>= to_shift;
    

    Ich ging jetzt davon aus, dass der Compiler das alleine schafft.

    void rshift_arr( unsigned char* bytes,
    				 std::size_t length,
    				 std::size_t to_shift )
    {
    	while( length-- )
    	{
    		bytes[length] >>= to_shift;
    
    		if( length )
    			bytes[length] |= (bytes[length - 1] << (CHAR_BIT - to_shift));
    	}
    }
    

    Deine ersten Beiden Punkte fallen weg, ohne den Algorithmus überhaupt nur anzufassen...
    der Rest scheint mir dazu erfunden um mich noch mehr zu kritisieren. 👎

    dr. bastel schrieb:

    Sone schrieb:

    Nein, die Lösung funktioniert nur solange das Array von der Gesamtgröße her nicht größer ist als ein Skalar.

    cl90 schrieb:

    Also es gehören immer 4 Bytes zusammen,[...]

    🙂 Habe den OP nicht richtig angeguckt.



  • Weil es so nicht geht. Das Prinzip lässt sich nicht mit einer negativen shift-Breite in einen links-Shift umwandeln, deswegen heißt es explizit rshift.

    Man merkt, was für eine Sorte du bist.

    Ich spielte darauf ab, dass du assert(to_shift < CHAR_BIT) hinschreiben sollst, weil die Funktion sonst garantiert von irgendjemandem falsch verwendet wird. Also quasi

    void bitshift(unsigned char* s, size_t n, unsigned rshift)
    {
      assert(rshift<CHAR_BIT);
    
      unsigned char carry=0,tmp;
      for (size_t i=rshift?0:n; i<n; ++i) {
        tmp = carry; carry = s[i]<<(CHAR_BIT-rshift);
        s[i] = tmp | (s[i]>>rshift);
      }
    }
    

    Aber warum <CHAR_BIT? Die Einschränkung lässt sich leicht beheben:

    void bitmove(unsigned char* s, size_t n, int rshift)
    {
      if (rshift >= CHAR_BIT) {
        unsigned m = rshift/CHAR_BIT; rshift %= CHAR_BIT;
        memmove(s+m, s, n - m);
        memset(s, 0, m);
      } else if (rshift < 0) {
        unsigned m = (CHAR_BIT-1-rshift)/CHAR_BIT;
        rshift = (CHAR_BIT + (rshift%CHAR_BIT))%CHAR_BIT;
        memmove(s, s+m, n - m);
        memset(s+m-n, 0, m);
      }
      bitshift(s, n, rshift);
    }
    


  • Sone schrieb:

    Klar, man könnte ... Umschreiben zu ...

    lieber

    for(auto index = N * sizeof(T); index; --index) {
        bytes[index] >>= to_shift;
        bytes[index] |= (bytes[index - 1] << (CHAR_BIT - to_shift));
    }
    

    Deine if-abfrage in der While-Schleife ergibt immer true



  • Cyres schrieb:

    Deine if-abfrage in der While-Schleife ergibt immer true

    Nein, das tut sie nicht, denkst du dann würde sie da stehen? 😉
    Schau mal genau hin.



  • Cyres schrieb:

    Deine if-abfrage in der While-Schleife ergibt immer true

    tut sie nicht, postdekrement und so...



  • Sone schrieb:

    Cyres schrieb:

    Deine if-abfrage in der While-Schleife ergibt immer true

    Nein, das tut sie nicht, denkst du dann würde sie da stehen? 😉
    Schau mal genau hin.

    narf, ich sollte mir abgewöhnen mitten in der Nacht Posts zu schreiben 😃


Anmelden zum Antworten