Forum: Mikrocontroller und Digitale Elektronik C Syntax Problem >>


von saxosun (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Stephan M. (stephanm)


Lesenswert?

> 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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Machs so, dann kommt das Gleiche raus:
1
value = value >> 1;
2
val += value;

von Gast (Gast)


Lesenswert?

Nicht ganz...

x >> 1

x wird halbiert und nicht verdoppelt.



val += value >>1;

=> Es die Hälfte von value in val addiert.

von Gast (Gast)


Lesenswert?

... Mist, den Verb vergessen ...

val += value >>1;

=> Es wird die Hälfte von value in val addiert.

von Gast (Gast)


Lesenswert?

> => Es wird die Hälfte von value in val addiert.
Und wenn value nun signed ist?
Dann klappt das mit dem Halbieren nicht.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Michael (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

Michael schrieb:
> ...
> ein nop macht. ich dachte, dass
>
> value >> 1;    genau das selbe wie     value = value >> 1; ist.
> ...

nein, das wäre value >>= 1;

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Tim S. (maxxie)


Lesenswert?

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.

von Juergen (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.