Hallo, ich habe mal eine Frage, was ist der Unterschied zwischen: value >> 1; val += value; und val += value >>1; Das erste funktioniert bei mir nicht, dass zweite sehr wohl. Ich verstehe nur nicht, warum das so ist. grüße Michael
saxosun schrieb: > Hallo, ich habe mal eine Frage, > was ist der Unterschied zwischen: > > value >> 1; > val += value; > > > und > > val += value >>1; > > Das erste funktioniert bei mir nicht, dass zweite sehr wohl. Ich > verstehe nur nicht, warum das so ist. Bei erstem wird val um den Inhalt von value erhöht. Bei zweitem wird value vorher auch noch um 1 Stelle nach rechts verschoben.
> Das erste funktioniert bei mir nicht, dass zweite sehr wohl. Was soll denn der Code machen? > value >> 1; Sollte vom Compiler in ein "nop" übersetzt werden. > val += value; val = val + value; > und val += value >>1; val = val + (value >> 1); Und jetzt? Stephan
Nicht ganz... x >> 1 x wird halbiert und nicht verdoppelt. val += value >>1; => Es die Hälfte von value in val addiert.
... Mist, den Verb vergessen ... val += value >>1; => Es wird die Hälfte von value in val addiert.
> => Es wird die Hälfte von value in val addiert.
Und wenn value nun signed ist?
Dann klappt das mit dem Halbieren nicht.
Gast schrieb: >> => Es wird die Hälfte von value in val addiert. > Und wenn value nun signed ist? > Dann klappt das mit dem Halbieren nicht. Offiziell überlässt der C-Standard das Verhalten dann der Implementierung. Und die verwenden meistens anstelle eines logischen Shifts in so einem Fall dann einen arithmetischen Shift und dann stimmts wieder (bei Verwendung des 2-er Komplements, welches ebenfalls vom C-Standard nicht gefordert wird) Aber wenn der Zweck der Übung tatsächlich eine Halbierung sein sollte, dann ist es sicherlich besser value = value / 2; zu schreiben. Ob es sinnvoll ist, diese Operation durch einen Shift-Operation zu implementieren überlässt man am besten dem Compiler.
Danke für die Antworten. Das Problem war wohl einfach, dass der Compiler aus value >> 1; ein nop macht. ich dachte, dass value >> 1; genau das selbe wie value = value >> 1; ist. Komisch finde ich nur, dass der Compiler bei: val += value >>1; das teilen/shiften akzeptiert. (Hat über zwei Stunden gedauert, bis ich das geschnallt hatte.) grüße Michael
Michael schrieb: > ... > ein nop macht. ich dachte, dass > > value >> 1; genau das selbe wie value = value >> 1; ist. > ... nein, das wäre value >>= 1;
Der Haken an der Sache ist, dass "value >> 1" den Wert "value" nicht verändert. Das Ergebnis der Operation wird nicht verwendet. Die ganze Zeile wird wegoptimiert (und nicht durch ein NOP ersetzt). Bei "val += value >> 1" wird das Ergebnis von "value >> 1" sehr wohl verwendet - und zwar zum Wert in "val" dazuaddiert.
Karl heinz Buchegger schrieb: > zu schreiben. Ob es sinnvoll ist, diese Operation durch einen > Shift-Operation zu implementieren überlässt man am besten dem Compiler. Nicht zuletzt, weil auch bei Zweierkomplement und entsprechenden Shifts x >> n und x / (1<<n) durchaus verschiedene Ergebnisse erbringen können. Nämlich dann wenn's negativ wird. Der Shift rundet anders als die Division.
Komisch ist das nicht. value >> 1 ; Shiftet ebenfalls nur wird das Ergebnis nicht verwendet und so bereits ohne Optimierung einfach weggelassen. In der CMa würde in etwa
1 | loada value |
2 | load 1 |
3 | shiftr
|
4 | pop
|
generiert werden. Also der Wert von value und 1 in den Stack geladen. Der Shift konsumiert beide und legt das Ergebnis des Shifts auf den Stack ab. anschliessend (die Übersetzung des ;) wird ein Wert auf dem Stack konsumiert. Benutzt du value >> 1 in einer Zuweisung (result = value >> 1), dann ändert sich etwas:
1 | loada value |
2 | load 1 |
3 | shiftr
|
4 | storea result |
5 | pop
|
Bevor der Stack nach dem Ausdruck aufgeräumt wird, wird er gespeichert. Aber auch hier bleibt der Inhalt von value unverändert. val += value >>1; Erzeugt in etwa
1 | loada val |
2 | loada value |
3 | load 1 |
4 | shiftr
|
5 | add
|
6 | storea val |
7 | pop
|
Es bleibt auch hier value unverändert. Das Zwischenergebnis des Shift wird auf dem CMa-Stack aber sofort gemeinsam mit der Inhalt von val konsumiert und die Summe auf dem Stack abgelegt, die dann in val zurückgespeichert wird. Anschliessend wird auch hier der CMa Stack wieder durch das ";" aufgeräumt.
> Und wenn value nun signed ist? > Dann klappt das mit dem Halbieren nicht. Doch, nur dass dann sowohl der Originalwert als auch das Ergebnis negativ sein koennen. Genau deshalb wird bei signed das oberste Bit geklont anstatt es auf null zu setzen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.