w &= 0xfffffffc
-
wenn ich nicht ganz falsch liege könnte man sagen das statement macht w durch 4 teilbar.
-
Vielen Dank für die schnelle Hilfe.
Habe mich bisher nie wirklich mit den Bit-Operatoren beschäftigt.
Sie ersparen zwar Schreibarbeit, machen den Code aber (für mich) unübersichtlich.
-
void TruncateWidth(unsigned& w) { w -= w % 4; }erzeugt den gleichen Code, wenn der Compiler was taugt. Beachte die Verwendung von unsigned hier, denn bei negativen ints ist das Ergebnis des and (bei 2er Komplement) nicht durch 4 teilbar.
-
Sieht auf jeden Fall übersichtlicher aus.
Da w die Breite eines Bildes angibt, sollten negative Werte ausgeschlossen werden. Daher ist unsigned natürlich auch eine gute Idee.
Danke.
-
camper schrieb:
void TruncateWidth(unsigned& w) { w -= w % 4; }erzeugt den gleichen Code, wenn der Compiler was taugt. Beachte die Verwendung von unsigned hier, denn bei negativen ints ist das Ergebnis des and (bei 2er Komplement) nicht durch 4 teilbar.
hm ok stimmt, daran habe ich gar nicht gedacht.
bin aufgrund der breitenangabe eines bildes von positiven werten ausgegangen.
-
camper schrieb:
void TruncateWidth(unsigned& w) { w -= w % 4; }erzeugt den gleichen Code, wenn der Compiler was taugt.
void TruncateWidth (unsigned& w) { w = (w>>2)<<2; }erzeugt den gleichen Code, wenn der Compiler was taugt.
-
C++Fan 2009 schrieb:
camper schrieb:
void TruncateWidth(unsigned& w) { w -= w % 4; }erzeugt den gleichen Code, wenn der Compiler was taugt.
void TruncateWidth (unsigned& w) { w = (w>>2)<<2; }erzeugt den gleichen Code, wenn der Compiler was taugt.
Bei
unsignedkann man ja wieder ohne Bedenken bzgl Portabilitätvoid TruncateWidth (unsigned & w) { return w & -4; }schreiben.
-
Jetzt, wo ich verstehe was da abläuft, kann ich's ja so lassen.
Aber vielen Dank an Alle.
-
Sebastian Pizer schrieb:
Bei
unsignedkann man ja wieder ohne Bedenken bzgl Portabilitätvoid TruncateWidth (unsigned & w) { return w & -4; }schreiben.
bloß das
void TruncateWidth (unsigned & w)keinen rückgabewert hat...
sry für [klugscheiß].
-
Keithy schrieb:
Sebastian Pizer schrieb:
Bei
unsignedkann man ja wieder ohne Bedenken bzgl Portabilitätvoid TruncateWidth (unsigned & w) { return w & -4; }schreiben.
bloß das
void TruncateWidth (unsigned & w)keinen rückgabewert hat...
sry für [klugscheiß].Richtig. Ich hatte es zwischendurch zu einer Funktion a la
unsigned TruncateWidth (unsigned w)
geändert und dann nur zur Hälfte wieder zurück. So muss es natürlich
w &= -4;
heißen.Gruß,
SP
-
Sebastian Pizer schrieb:
Bei
unsignedkann man ja wieder ohne Bedenken bzgl Portabilitätvoid TruncateWidth (unsigned & w) { return w & -4; }schreiben.
wieso? muss -4 auf jedem system dieser erde 0xfffffffc sein?

-
Basher schrieb:
wieso? muss -4 auf jedem system dieser erde 0xfffffffc sein?

Das nicht, aber es wird ja implizit zu einem unsigned konvertiert, bevor & angewendet wird. unsigned(-4) liefert garantiert eine vorzeichenlose Zahl mit Bitmuster "11...1100" -- auch, wenn Du einen Exoten hast, der für vorzeichenbehaftete Ganzzahlen nicht das 2er-Komplement benutzt.
-
Sebastian Pizer schrieb:
Basher schrieb:
wieso? muss -4 auf jedem system dieser erde 0xfffffffc sein?

Das nicht, aber es wird ja implizit zu einem unsigned konvertiert, bevor & angewendet wird. unsigned(-4) liefert garantiert eine vorzeichenlose Zahl mit Bitmuster "11...1100".
wenn nun aber für negative zahlen kein zweier-, sondern z.b. einerkomplement benutzt wird (sowas solls ja geben), dann ist -4 111...1011. damit löschste nur bit 2 weg, nicht bit 1 und 0, wie geplant.
btw, noch 'ne variante:unsigned TruncateWidth (unsigned w) { return (w/4)*4; }
-
Basher schrieb:
wenn nun aber für negative zahlen kein zweier-, sondern z.b. einerkomplement benutzt wird (sowas solls ja geben), dann ist -4 111...1011.
Spielt keine Rolle. Der C++ Standard sagt genau, was passiert, wenn Du eine vorzeichenbehaftete Zahl zu einer vorzeichenlosen Zahl konvertierst. Das Bitmuster, was Du danach erhälst entspricht immer dem 2er-Komplement.
-
Sebastian Pizer schrieb:
Der C++ Standard sagt genau, was passiert, wenn Du eine vorzeichenbehaftete Zahl zu einer vorzeichenlosen Zahl konvertierst. Das Bitmuster, was Du danach erhälst entspricht immer dem 2er-Komplement.
biste sicher? was passiert bei:
// angenommen: negative zahlen sind einerkomplement, 'signed magnitude' oder was anderes unsigned a = (unsigned)-4; // <-- a enthält jetzt bitmuster von -4 im zweierkomplement, nach deiner aussage int b = (int)a; // bekommen wir hier unsere -4 zurück? wohl kaum.
-
Basher schrieb:
biste sicher?
Ja. Soll ich jetzt noch die Stelle aus dem Standard raussuchen? Müste irgendwo bei "standard conversions" sein. Das mit dem Bitmuster ergibt sich aus der Regel, dass bei "u=s;" -- wobei u eine vorzeichenlose Integervariable und s irgend eine andere Integervariable (meinetwegen auch long) ist -- folgendes gilt:
u = s modulo (2 hoch N), N ist hier die Zahl der Bits in u.Basher schrieb:
was passiert bei:
// angenommen: negative zahlen sind einerkomplement, 'signed magnitude' // oder was anderes unsigned a = (unsigned)-4; // <-- a enthält jetzt bitmuster von // -4 im zweierkomplement, nach deiner aussage int b = (int)a; // bekommen wir hier unsere -4 zurück? wohl kaum.Nein. Konvertieren in eine vorzeichenbehaftete Zahl ist "implementation-defined", falls der zugewiesene Wert nicht im Wertebereich liegt. Steht auch so im Standard. Guck mal selbst nach. :p
Gruß,
SP
-
msvc++
ohne probleme kommt da -4 raus. bitmuster bei beiden: 0xfffffffc

-
Für meinen Geschmack ist das diese Variante (x & -4u) ein bisschen zu subtil, auch wenn ich zugeben muss, dass ich das früher auch so geschrieben habe.
x & ~(4u-1) ist vielleicht ein bisschen besser. Bei heutigen Compilern gibt es aber eigentlich nur noch selten einen Grund, das im Code stehen zu lassen.
Sowas hab ich in der Wildnis auch schon gesehen:int foo; while ( foo % 4 != 0 ) foo--;Da ziehe ich dann sogar ein einfaches & vor

-
Sebastian Pizer schrieb:
Das mit dem Bitmuster ergibt sich aus der Regel, dass bei "u=s;" -- wobei u eine vorzeichenlose Integervariable und s irgend eine andere Integervariable (meinetwegen auch long) ist -- folgendes gilt:
u = s modulo (2 hoch N), N ist hier die Zahl der Bits in u.das glaube ich dir, aber das daraus in jedem fall ein zweierkomplement wird, egal mit welcher kodierung ein system negative zahlen speichert, kann ich mir nicht vorstellen.
helferlein schrieb:
msvc++
ohne probleme kommt da -4 raus. bitmuster bei beiden: 0xfffffffcwir reden hier von 'nicht-zweierkomplement' systemen.
camper schrieb:
Für meinen Geschmack ist das diese Variante (x & -4u) ein bisschen zu subtil...
finde ich auch.

-
da wir jetzt alle 1000 tricks kennen, die unteren zwei bits zu löschen, mal andersrum: wie kommt man am schnellsten auf das nächste grössere vielfache von 4? bitte, postet eure vorschläge....
