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,[...]

-
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 negativeEin 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önntewhile( 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 quasivoid 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
