Gast
#1098892
Hallo, man kann eine Zahl anhand des Nach-rechts-schiftens dividieren. z.B. a >> 3 heisst, dass ich die Zahl a durch 8 dividiere Frage: Funktioniert das auch mit negativen Zahlen (long)? Danke!
|
Anzeige
|
Dividieren durch Schiften
Gast
#1098892
Hallo, man kann eine Zahl anhand des Nach-rechts-schiftens dividieren. z.B. a >> 3 heisst, dass ich die Zahl a durch 8 dividiere Frage: Funktioniert das auch mit negativen Zahlen (long)? Danke! FrageMan wrote: > Frage: > Funktioniert das auch mit negativen Zahlen (long)? Wenn du Glück hast. Ja, es ist wirklich so, es ist dem Compiler überlassen ob er das richtig macht oder nicht. Viele Compiler machen das richtig, wenn es z.B. einen Arithmetischen Shift gibt, aber eben nicht alle. Im Sinne einer Portierbaren Lösung sollte man das daher vermeiden. Wie Benedikt schon bemerkt hat, ist das Verhalten "implementationsspezifisch". Am Besten ist, du programmierst eine Integer-Division durch 2^n und überlässt es der Optimierung des Compilers, daraus den richtigen Prozessor-Code zu machen. Selbst wenn ein arithmetischer Shift gemacht wird, solltest du beachten, daß das nicht analog zu posiiven Zahlen wirkt. Beispiel: 1 >> 1 = 0 aber (-1) >> 1 = -1 oder anders ausgedrückt: i.d.R ist Der Einwand von Johann L. ist korrekt. Davon abgesehen klappt es mit dem Shiften, wenn man es richtig macht. Es ist nämlich keineswegs Glückssache in C, sondern klar geregelt: - Beim Shiften nach links werden generell von rechts Nullen nachgezogen - Beim Shiften eines signed-Wertes (short, int, long, long long, signed, signed short, signed int, signed long, signed long long, signed char) nach rechts wird immer das bisherige oberste Bit zum Auffüllen links verwendet, also eine 0 bei positiven und eine 1 bei negativen Zahlen. - Beim Shiften eines unsigned-Wertes (unigned, unsigned int, unsigned char, unsigned short, unsigned long, unsigned long long) nach rechts wird links mit 0 aufgefüllt. Hast du also eine vorzeichenbehaftete Zahl, dann wird beim Rechtsshiften eine positive Zahl positiv bleiben und eine negative wird negativ bleiben. Das wird von allen C-Standards so vorgeschrieben (außer daß in älteren Varianten kein long long zu finden ist natürlich). (Das einzige ungeregelte daran ist die Frage, ob ein char (ohne signed oder unsigned davor) als signed char oder als unsigned char zu behandeln ist. Das ist vom Compiler abhängig bzw. kann meistens über Compilerparameter eingestellt werden.) mfgkw Warum nimmst Du nicht einfach den Divisionsoperator? Compiler sind heutzutage durchaus in der Lage, zu erkennen, dass die Division gegebenenfalls durch Schiebeoperationen ersetzt werden kann? Vorteil: Es funktioniert. Gruß Marcus http://www.doulos.com/arm Klaus Wachtler wrote: > - Beim Shiften eines signed-Wertes (short, int, long, long long, > signed, signed short, signed int, signed long, signed long long, > signed char) nach rechts wird immer das bisherige oberste Bit > zum Auffüllen links verwendet, also eine 0 bei positiven und eine > 1 bei negativen Zahlen. Kühne Aussage. Du hast sicherlich auch sofort die entsprechende Stelle im Standard parat, die deine Aussage hinterlegt, oder? Falls nicht: ich könnte dir dafür sofort die Stelle zitieren, die deine Aussage widerlegt... Klaus Wachtler wrote: > Es ist nämlich keineswegs Glückssache in C, sondern klar geregelt: > ... > - Beim Shiften eines signed-Wertes (short, int, long, long long, > signed, signed short, signed int, signed long, signed long long, > signed char) nach rechts wird immer das bisherige oberste Bit > zum Auffüllen links verwendet, also eine 0 bei positiven und eine > 1 bei negativen Zahlen. > ... > Hast du also eine vorzeichenbehaftete Zahl, dann wird beim Rechtsshiften > eine positive Zahl positiv bleiben und eine negative wird negativ > bleiben. > Das wird von allen C-Standards so vorgeschrieben (außer daß in älteren > Varianten kein long long zu finden ist natürlich). Das stimmt einfach nicht. Im aktuellen Standard steht:
ok, bzgl. des Standards war ich wohl zu vorlaut (je nachdem, aus welchem du da jetzt zitierst) und habe auch keinen hier greifbar. Faktisch ändert es aber nichts, solange die Compiler sich so verhalten wie von mir beschrieben. Relevant dürfte hier ja vor allem der gcc sein. Unter http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Integers-implementation.html#Integers-implementation steht:
Zum Vergleich Visual Studio VS2005 (aus der Online-Hilfe):
Also könnte man schon so arbeiten. Gegen eine Division spricht natürlich immer noch nichts... mfgkw
Gast
#1099122
>Gegen eine Division spricht natürlich immer noch nichts...
Dann warte ab, bis die Puristen wach werden und an Deinem Code noch 2,37
Bit einsparen wollen.
Oder mache eine reziproke Multiplikation am besten mit Fixkomma.
Irgendwie muß man doch Fehler in den Code bekommen. Nicht wahr?
Gast wrote: >>Gegen eine Division spricht natürlich immer noch nichts... > Dann warte ab, bis die Puristen wach werden und an Deinem Code noch 2,37 > Bit einsparen wollen. Sie sparen nichts damit. Genau das ist ja der Punkt. Ein ordentlicher Compiler entdeckt eine Division durch konstante 2**N zur Compilezeit und implementiert sie als Schiebeoperation, falls das Sinn hat.
Gast
#1099245
Dass der Standard für negativen Zahlen die Division spezifiziert, den Rechts-Shift aber nicht, war mir bisher auch nicht bewusst, da ich generell diese Operationen mit negativen Zahlen zu vermeiden versuche. In meinen Augen wäre es aber umgekehrt (also den Shift statt der Division zu spezifizieren) logischer: Praktisch jeder Prozessor hat einen ASR-Befehl (oder ein Äquivalent mit anderem Namen), der sich (bis auf die Bitbreite) auf allen Prozessoren gleich verhält und damit eine einheitliche und trotzdem effiziente Implementierung des >>-Operators für vorzeichenbehaftete Zahlen zuließe. Einen Divisionsbefehl hingegen haben nur manche Prozessoren, und ich wäre mir nicht ganz so sicher, ob das Divisionsergebnis bei allen nach C-Standard (also zur Null hin) gerundet wird. Ok, bei den aktuellen Prozessoren wird der C-Standard für die Division sicher schon bei der Entwicklung berücksichtigt, aber beim ASR stellt sich die Frage der Rundungsrichtung erst gar nicht. Ich frage mich nun, ob es für einen konkreten Compiler (bspw. den AVR-GCC) einen standardkonformen C-Ausdruck gibt, der sich exakt wie der ASR-Befehl verhält (also eine immer in negative Richtung rundende Division durch 2) und auch als solcher übersetzt wird. Folgende Möglichkeiten wären denkbar (a und b sind beide int8_t):
liefert zwar das gewünschte Ergebnis und wird tatsächlich in einen einzelnen ASR-Befehl übersetzt, ist aber nicht standardkonform, da >> für negatives a nicht spezifiziert ist.
ist zwar standardkonform, liefert aber ein anderes Ergebnis und ist weniger effizient, da der Compiler zusätzliche Befehle zur Vorzeichenkorrektur generiert.
bzw.
sind zwar standardkonform und liefern das gewünschte Ergebnis, enden jedoch in sehr ineffizientem Code. Hat jemand vielleicht eine bessere Lösung dieses Problems? An dieser Stelle ist der Standard meiner Meinung nach einfach etwas daneben. Ich würde folgende Spezifikation als sehr viel praxisnäher betrachten: - Der >>-Operator liefert für a>>b den um b Bits nach rechts geschobenen Wert von a, wobei die frei werdenden höchstwertigen b Bits des Ergebnisses gleich 0 werden, wenn a vorzeichenlos ist, und gleich dem höchstwertigen Bit von a, wenn a vorzeichenbehaftet ist. - Der /-Operator liefert das Ergebnis der Division der beiden Operanden auf die nächstkleinere (d.h. negativere) ganze Zahl gerundet. Ist der rechte Operand negativ, ist das Ergebnis undefiniert (damit wenigstens etwas unspezifiziert bleibt :) ). - Der %-Operator liefert für a%b das Ergebnis a-(a/b)*b. Auch hier ist das Ergebnis für negatives b undefiniert. Mit diesen Regeln wären a>>1 und a/2 auch für negatives a äquivalent, die Funktion f(x)=x/c wäre für konstantes c eine saubere Treppenfunk- tion, die im Gegensatz zum offiziellen Standard auch an der Stelle 0 eine Stufe hat und damit gleichmäßig von den negativen in die positiven Werte übergeht. Schließlich läge das Ergebnis von a%b immer im Intervall [0,b-1], das genauso viele Elemente enthält wie es Restklassen modulo b gibt. Im offiziellen Standard liegt das Ergebnis dagegen in dem fast doppelt so großen Intervall [-b+1,b-1], in dem jede Restklasse außer der 0 durch zwei Werte repräsentiert wird, bspw. (1 und -b+1), (2 und -b+2) und (b-1 und -1), was sich in der Praxis oft störend auswirkt. Aber mich hat ja damals keiner gefragt ;-)
Gast
#1099289
> b = a>>1; > > liefert zwar das gewünschte Ergebnis und wird tatsächlich in einen > einzelnen ASR-Befehl übersetzt, ist aber nicht standardkonform, da > >> für negatives a nicht spezifiziert ist. Es ist "implementation-defined", nicht "unspecified". Das sind zwei verschiedene Dinge. Bei ersterem muß in der Dokumentation des Compilers angegeben sein, was er daraus macht. > Hat jemand vielleicht eine bessere Lösung dieses Problems? Wie oft brauchst du denn den Shift für negative Zahlen? Also sprich, bewußt eine Division durch eine Zweierpotenz, bei der aber die Rundung für negative Werte falsch sein soll? > - Der >>-Operator liefert für a>>b den um b Bits nach rechts > geschobenen Wert von a, wobei die frei werdenden höchstwertigen b > Bits des Ergebnisses gleich 0 werden, wenn a vorzeichenlos ist, und > gleich dem höchstwertigen Bit von a, wenn a vorzeichenbehaftet ist. Bei allen in der C-Norm möglichen Repräsentationen vorzeichenbehafteter Zahlen? Deine Definition gibt nämlich nur bei Zweierkomplement wirklich einen Sinn. > - Der /-Operator liefert das Ergebnis der Division der beiden > Operanden auf die nächstkleinere (d.h. negativere) ganze Zahl > gerundet. Das wäre aber sehr schlecht, denn erstens erwartet man meistens eine Rundung gegen 0, zweitens wird genau die auch von Divisions-Einheiten in den Prozessoren, die sowas haben, implementiert. Der Compiler müßte dann für eine Division umständlich die Rundung gegen 0 kaputtmachen. > Ist der rechte Operand negativ, ist das Ergebnis undefiniert (damit > wenigstens etwas unspezifiziert bleibt :) ). "undefined" ist nochmal was anderes als "unspecified" und "implementation-defined". Da wird streng unterschieden. Und warum darf nur der rechte Operand nicht negativ sein?
Gast
#1099611
>> b = a>>1; >> […] ist aber nicht standardkonform, da >> für negatives a nicht >> spezifiziert ist. > > Es ist "implementation-defined", nicht "unspecified". Das sind zwei > verschiedene Dinge. Ok, entschuldige bitte den falschen Ausdruck. Dann ist der Ausdruck eben nicht nicht standardkonform, sondern — zumindest gemäß Standard — nicht portabel. > Wie oft brauchst du denn den Shift für negative Zahlen? Also sprich, > bewußt eine Division durch eine Zweierpotenz, bei der aber die Rundung > für negative Werte falsch sein soll? Den Shift als solchen mit negativen Zahlen habe ich bisher recht selten gebraucht, ein paar Mal für irgendwelche trickreichen Bitpopeleien, an die ich micht aber nicht mehr genau erinnern kann. Was ich aber häufig brauchen könnte, wäre eine Division mit Abrunden. Die einfachste Anwendung dafür ist eine Division mit "normalem" Runden (also ab 0,5 auf-, sonst abrunden), die man dann ganz einfach als
schreiben könnte, bei der Division nach C-Standard aber eine Fallunterscheidung nach positiven und negativen Werten erfordert. Es gibt aber noch viel mehr Fälle, vor allem im Zusammehang mit Modulo-Operationen, wo eine einheitliche Rundungsrichtung praktisch wäre. >> - Der >>-Operator liefert für a>>b den um b Bits nach rechts >> geschobenen Wert von a, wobei die frei werdenden höchstwertigen b >> Bits des Ergebnisses gleich 0 werden, wenn a vorzeichenlos ist, und >> gleich dem höchstwertigen Bit von a, wenn a vorzeichenbehaftet ist. > > Bei allen in der C-Norm möglichen Repräsentationen > vorzeichenbehafteter Zahlen? Deine Definition gibt nämlich nur bei > Zweierkomplement wirklich einen Sinn. Dann sollte der Standard das Zweierkomplement als einzig erlaubtes Signed-Integer-Format vorschreiben. Ich kenne keinen seit der Einführung von C produzierten Mikroprozessor, der nicht im Zweierkomplement rechnet (lasse mich aber gerne eines Besseren belehren), wo läge also das Problem? Der C-Standard berücksichtigt ja auch keine Prozessoren, die statt im Binär- im Ternärsystem rechnen. Als Bitoperationen haben die Schiebebefehle aber ohnehin nichts mit Arithmetik und damit auch wenig mit der internen Zahlendarstellung zu tun. Hat ein Prozessor also eine andere Zahlendarstellung als das Zweierkomplement, bedeutet das für meine obige Spezifikation nur, dass man den >>-Operator nicht für Divisionen durch Zweierpotenzen missbrauchen kann. Aber das sollte man ja sowieso nicht. >> - Der /-Operator liefert das Ergebnis der Division der beiden >> Operanden auf die nächstkleinere (d.h. negativere) ganze Zahl >> gerundet. > > Das wäre aber sehr schlecht, denn erstens erwartet man meistens eine > Rundung gegen 0, Wer ist "man"? Du? Ich jedenfalls nicht. Wenn ich es nicht besser wüsste, würde ich erwarten, dass das Ergebnis unabhängig vom Vorzeichen immer abgerundet wird, ähnlich wie es die Floor-Funktion bei FP-Zahlen macht. > zweitens wird genau die auch von Divisions-Einheiten in den > Prozessoren, die sowas haben, implementiert. Die Prozessoren machen das deswegen so, weil es der C-Standard so möchte. >> Ist der rechte Operand negativ, ist das Ergebnis undefiniert (damit >> wenigstens etwas unspezifiziert bleibt :) ). > > "undefined" ist nochmal was anderes als "unspecified" und > "implementation-defined". Da wird streng unterschieden. > Und warum darf nur der rechte Operand nicht negativ sein? Ja, da habe ich schon wieder den falschen Begriff verwendet. Ich meinte auch hier "implementation-defined". Grund: Bei einer Division durch negative Zahlen fallen mir einfach keine schlüssigen Gründe für die Rundung in die eine oder in die andere Richtung ein. Da man sie bei Integer-Zahlen so gut wie nie braucht, habe ich gedacht, ich gestehe die Auswahl der Rundungsrichtung den Prozessorherstellern zu ;-)
Gast
#1099721
> Dann sollte der Standard das Zweierkomplement als einzig erlaubtes > Signed-Integer-Format vorschreiben. Tut er aber mit Absicht nicht. Er läßt auch Einerkomplement und Sign/Magnitude-Darstellung zu. Würde er das nicht tun, wäre auf entsprechenden Prozessoren ein C-Compiler nicht mehr sinnvoll umsetzbar. > Ich kenne keinen seit der Einführung von C produzierten > Mikroprozessor, der nicht im Zweierkomplement rechnet (lasse mich > aber gerne eines Besseren belehren), wo läge also das Problem? Nur weil du keinen kennst, heißt das nicht, daß es keinen gibt. In einer Diskussion im Usenet zu dem Thema wurden da auch Architekturen genannt, aber ich weiß nicht mehr welche, weil ich damit nicht arbeite. > Als Bitoperationen haben die Schiebebefehle aber ohnehin nichts mit > Arithmetik und damit auch wenig mit der internen Zahlendarstellung > zu tun. Heißt der ASM-Befehl, um den es hier geht, deshalb üblicherweise "arithmetischer Shift"? ;-) > Hat ein Prozessor also eine andere Zahlendarstellung als das > Zweierkomplement, bedeutet das für meine obige Spezifikation nur, > dass man den >>-Operator nicht für Divisionen durch Zweierpotenzen > missbrauchen kann. Aber das sollte man ja sowieso nicht. Aber ich dachte, gerade darum ginge es dir. Wenn du ihn nicht dazu verwenden willst, sollte dich beim Schieben auch das Vorzeichenbit nicht interessieren. Dann brauchst du auch nur den vorzeichenlosen Shift, weil man Bitbasteleien eh am besten mit vorzeichenlosen Zahlen macht. >> Das wäre aber sehr schlecht, denn erstens erwartet man meistens >> eine Rundung gegen 0, > > Wer ist "man"? Du? > > Ich jedenfalls nicht. Ok, eine nearest-Rundung wäre auch nicht überraschend. > Wenn ich es nicht besser wüsste, würde ich erwarten, dass das > Ergebnis unabhängig vom Vorzeichen immer abgerundet wird, ähnlich > wie es die Floor-Funktion bei FP-Zahlen macht. Das wäre jetzt z.B. das, was ich überhaupt nicht erwarten würde, sondern zumindest, daß beim negieren eines der Operanden auch das Ergebnis nur negiert wird und vom Betrag her auf jeden Fall gleich bleibt. > Die Prozessoren machen das deswegen so, weil es der C-Standard so > möchte. Das glaube ich eher nicht. Es gibt ja auch genügend andere Programmiersprachen. Aber selbst wenn. Das wurde ja nicht willkürlich so festgelegt.
Gast
#1099899
>> Ich kenne keinen seit der Einführung von C produzierten >> Mikroprozessor, der nicht im Zweierkomplement rechnet (lasse mich >> aber gerne eines Besseren belehren), wo läge also das Problem? > > Nur weil du keinen kennst, heißt das nicht, daß es keinen gibt. In > einer Diskussion im Usenet zu dem Thema wurden da auch Architekturen > genannt, aber ich weiß nicht mehr welche, weil ich damit nicht > arbeite. Habe gerade mal gesucht: Ja, es gab die PDP-1 und die UNIVAC 1100/2200, die beide vorzeichenbehaftete Integers im Einerkomplement darstellten. Beide wurden Anfang der 60er-Jahre eingeführt, allerdings reichen die letzten Nachfolger der UNIVAC noch deutlich in die C-Ära hinein. Damit wäre geklärt, warum das C-Konsortium dieses (heute unübliche) Zahlenformat im Standard berücksichtigen mussten. >> Als Bitoperationen haben die Schiebebefehle aber ohnehin nichts mit >> Arithmetik und damit auch wenig mit der internen Zahlendarstellung zu >> tun. > > Heißt der ASM-Befehl, um den es hier geht, deshalb üblicherweise > "arithmetischer Shift"? ;-) In Assembler wird der Befehl ja tatsächlich für Divisionen eingesetzt. Aber in C gibt es ja die /-Operation, die von einem halbwegs aktuellen Compiler, wo möglich, in eine Shift-Operation übersetzt wird, so dass die >>-Operation eigentlich den Bitspielereien vorbehalten sein sollte. >> Hat ein Prozessor also eine andere Zahlendarstellung als das >> Zweierkomplement, bedeutet das für meine obige Spezifikation nur, >> dass man den >>-Operator nicht für Divisionen durch Zweierpotenzen >> missbrauchen kann. Aber das sollte man ja sowieso nicht. > > Aber ich dachte, gerade darum ginge es dir. Nicht primär. Zum einen ging es mir um die abrundende Division. Schön, aber nicht unbedingt erforderlich wäre es zusätzlich, wenn >> einer Division durch eine Zweierpotenz entspräche, genauso wie << einer Multiplikation mit einer Zweierpotenz entspricht, auch für negative Zahlen. Das haben die Hersteller gängiger C-Compiler für Zweierkomplementprozessoren auch bestmöglich realisiert, indem sie >> für vorzeichenbehaftete Zahlen anders übersetzen (nämlich in einen ASR) als für vorzeichenlose (LSR), obwohl nach Standard (implementation-defined) auch für beide Fälle einheitlich ein LSR erlaubt wäre. Damit entspricht >> zwar auch für vorzeichenbehaftetes a weitgehend einer Division, aber eben nicht exakt, wegen der Rundung. Zum anderen ging es mir um die Frage, ob es einen C-Ausdruck gibt, der unabhängig vom verwendeten Compiler das gleiche wie der ASR-Befehl gängiger Prozessoren tut, und der zumindest von einigen ausgewählten Compilern auch tatsächlich in einen ASR übersetzt wird. Wobei diese Frage eher akademischer Natur ist. >> Die Prozessoren machen das deswegen so, weil es der C-Standard so >> möchte. > > Das glaube ich eher nicht. Es gibt ja auch genügend andere > Programmiersprachen. Aber selbst wenn. Das wurde ja nicht willkürlich > so festgelegt. In BCPL bspw. war die Division noch implementationsabhängig: The division operator / yields the correct result of [the division of E1 by E2 if] El is divisible by E2; it is otherwise implementation dependent but the rounding error is never greater than 1. The operator rem yields the remainder of El divided by E2; its exact specification is Implementation dependent. Das könnte darauf hindeuten, dass es damals, also vor der Einführung von C, Rechner mit unterschiedlichem Rundungsverhalten bei Divisionen gab. Aber was soll's: Es ist nun einmal alles so wie es ist, und da ich nicht erwarte, dass C, die Compiler und die Prozessoren wegen mir geändert werden, finde ich mich ja auch gerne damit ab :) Nicht dass ein falscher Eindruck ensteht: Alles in allem ist C für mich immer noch die beste Hochsprache für hardwarenahe und eine der besten für viele sonstige Anwendungen. Da sehe ich gerne über ein paar kleine Schönheitsfehler hinweg, die vielleicht sogar nur mir als solche erscheinen ;-) yalu wrote: > Zum einen ging es mir um die abrundende Division. Schön, aber nicht > unbedingt erforderlich wäre es zusätzlich, wenn >> einer Division durch > eine Zweierpotenz entspräche, genauso wie << einer Multiplikation mit > einer Zweierpotenz entspricht, auch für negative Zahlen. Das haben die > Hersteller gängiger C-Compiler für Zweierkomplementprozessoren auch > bestmöglich realisiert, indem sie >> für vorzeichenbehaftete Zahlen > anders übersetzen (nämlich in einen ASR) als für vorzeichenlose (LSR), > obwohl nach Standard (implementation-defined) auch für beide Fälle > einheitlich ein LSR erlaubt wäre. Damit entspricht >> zwar auch für > vorzeichenbehaftetes a weitgehend einer Division, aber eben nicht exakt, > wegen der Rundung. Um die Lage weiter zu komplizieren und meiner obigen Ungleichung eine weitere hinzuzufügen, ist i.A. Dies tritt idR dann auf, wenn der Shift-Offset zur Compilezeit unbekannt ist und die Bitbreite des Operanden überschreitet. Zum Beispiel ist 0xffff, wenn man es 20 mal nach rechts shiftet, zu 0 geworden. Hingegen ergibt sich nicht unbedingt 0, wenn man es um 20 nach rechts shiftet. Auf vielen Maschinen ein Tribut an die Effizenz der Shift-Instruktion und ihren Silizium-Verbrauch. Auch darin unterscheidet sich ein Shift von einer Division (hier durch 2^20) > Zum anderen ging es mir um die Frage, ob es einen C-Ausdruck gibt, der > unabhängig vom verwendeten Compiler das gleiche wie der ASR-Befehl > gängiger Prozessoren tut, und der zumindest von einigen ausgewählten > Compilern auch tatsächlich in einen ASR übersetzt wird. Wobei diese > Frage eher akademischer Natur ist. Generell nein. Nur ein recht nativer Compiler übersetzt C-Code-Schnippsel in vordefinierte Assembler-Schnippel. Ein gutes Beispiel dafür ist BASCOM für BASIC, gcc -O0 ein etwas schlechteres für C/C++. Bei einem optimierenden Compiler gibt es aber i.d.R. keine 1:1 Zuordnung zwischen C-Quelle und Asm. Praktisch alles an n:m Abbildungen ist denkbar, darunter auch n:0. Das einzige, was bei gcc sicher einen arithmetischen Shift zu erzeugen in der Lage wäre, wäre ein nicht portierbares __builtin_ashr oder so, das es jedoch nicht gibt. Gleiches gilt für rotate, daß sich zwar auch für avr-gcc erzeugen lässt, aber Sicherheit hat man eben keine. Bei GCC kannst du jedoch recht sicher sein, daß ein >> eines signed in einen ahift übersetzt wird, sofern die Maschine das kann. avr-gcc definiert dan ashift für 8-, 16- und 32-Bitwerte ("ashrqi3", "ashrhi3" und "ashrsi3" im md) Der Code, den er erzeugt, findest du beim Suchen nach diesen Strings in http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.c?revision=142783&view=markup Für r24 >>= 7 wird zum Beispiel ausgegeben
Gast
#1099982
> Um die Lage weiter zu komplizieren und meiner obigen Ungleichung eine > weitere hinzuzufügen, ist i.A. > Dies tritt idR dann auf, wenn der Shift-Offset zur Compilezeit > unbekannt ist und die Bitbreite des Operanden überschreitet. Ja, das ist klar. Da ist erst kürzlich jemand hier im Forum darübergestolpert. > Bei GCC kannst du jedoch recht sicher sein, daß ein >> eines signed in > einen ahift übersetzt wird, sofern die Maschine das kann. Ja, und der C-Compiler von MS macht es auch so (s. Beitrag von Klaus Wachtler), und wahrscheinlich kann man dies auch auf die meisten anderen Compiler extrapolieren.
Gast
#4898723
1 >> 1 = 0 aber (-1) >> 1 = -1 ist es nicht hier falsch, da (-1) >>1 = -0.5 in Dezimal also 1.11 in Zweierkomplement ? amna schrieb: > ist es nicht hier falsch Wurde bereits im zweiten Beitrag geklärt: Verschieben negativer Zahlen ist “implementation defined”. Und jetzt ab in die Kiste mit dem Thread. |
Anzeige
|