Keine Checkung bei Bit-Shift
-
Kann mir jemand verraten, warum hier
printf("%u\n", ~0 ); // ULONG_MAX printf("%u\n", ~0 >> 1 ); printf("%d\n", ((int) ~0) ); // -1 printf("%d\n", ((int) ~0) >> 1 ); printf("%d\n", ((int) ~0) >> 2 ); printf("%u\n", ((int) ~0) ); // ULONG_MAX printf("%u\n", ((int) ~0) >> 1 ); printf("%u\n", ((int) ~0) >> 2 );
konstante Werte geliefert werden ?
( ULONG_MAX, -1, ULONG_MAX )
-
Was soll denn sonst rauskommen, variable Werte?
Warum du die Werte kriegst die du kriegst erklärt sich einerseits daraus, dass Computer im Binärsystem arbeiten (deshalb ULONG_MAX) und andererseits daraus, dass für negative Werte auf heutigen Rechnern die Zweierkomplementdarstellung verwendet wird: http://de.wikipedia.org/wiki/Zweierkomplement (in ANSI-C ist rein theoretisch auch Einerkommplement und Betrag/Vorzeichen möglich)
-
Das der Rechner im Binärsystem arbeitet weiss ich doch.
Die Berechnung einer im Binärsystem negativ dargestellten Zahl über das
Zweierkomplement kenne ich auch.Ein shiften um eine Position nach rechts bedeutet ja im binären eine Division durch zwei, shiften um zwei Positionen nach rechts bedeutet eine Division durch vier usw.
Umso mehr wundert mich ja, das in den obigen Fällen konstante Werte rauskommen.
( siehe Argumente hinter dem Bitshift Operator )
-
Der Vergleich
printf("%u\n", ULONG_MAX == ~0 );
liefert eine eins, ist also vom boolschen Standpunkt aus betrachtet wahr.Das hier
printf("%u\n", ULONG_MAX );
gibt mir wie erwartet den Wert ULONG_MAX = 4294967295 aus.
Und
printf("%u\n", ULONG_MAX >> 1 );
zeigt mir wie erwartet den Wert ULONG_MAX/2 = 2147483647 an. (mit abgeschnittenem Nachkommateil)Da ja ULONG_MAX = ~0 ist
und ULONG_MAX >> 1 = 2147483647
hätte ich nun z.B. für
printf("%u\n", ~0 >> 1 );
ebenfalls 2147483647 erwartet.
-
proggingmania schrieb:
Umso mehr wundert mich ja, das in den obigen Fällen konstante Werte rauskommen.
( siehe Argumente hinter dem Bitshift Operator )dich wundert, dass das shiften nichts bringt?
wenn rechts 'ne 1 ist, werden auch einsen reingeshiftet.
shifte doch mal 0x7fffffff nach rechts.
-
Ach jetzt versteh ich was du meinst. Es ist m.W. unspezifiziert (oder sogar undefiniert), negative Werte (wie ~0) nach rechts zu shiften. In deinem Fall wird ein arithmetischer Shift ausgeführt, es wird also -1 durch 2 geteilt und abgerundet, was wieder -1 ergibt. Auf Bitebene sieht das dann so aus, das beim Shiften von links 1en statt 0en nachrutschen, bzw. dass das Vorzeichen expandiert wird.
-
pale dog schrieb:
proggingmania schrieb:
Umso mehr wundert mich ja, das in den obigen Fällen konstante Werte rauskommen.
( siehe Argumente hinter dem Bitshift Operator )dich wundert, dass das shiften nichts bringt?
wenn rechts 'ne 1 ist, werden auch einsen reingeshiftet.
shifte doch mal 0x7fffffff nach rechts.
Das ist "unspecified behaviour".
@ proggingmania: Schau dir mal die Postfixe für Integer (im speziellen Fall u) an und überlege was das für einen Unterschied machen würde.
-
Die beiden Ausdrücke ~0 und (int) ~0 werden wohl undefiniert sein, weil ein shiften auf beide keine Änderung bewirkt, aber wohl auch nur beim shiften.
Anders jedoch ist es wenn man (unsigned int)~0 shiftet, dann ergibt das
ULONG_MAX/2 2147483647.
Womit sich für mich ein weiteres Rätsel auftutDiese undefinierte, negierte Null: ~0
scheint ja aber auch nur im Falle des shiftens undefiniert zu sein, weil ja
ein Vergleich ULONG_MAX = ~0
gleich 1 liefert.Das ist ein Widerspruch.
-
undefiniert ist, was bei right shift von vorzeichenbehafteten zahlen links rein kommt...
-
pale dog schrieb:
wenn rechts 'ne 1 ist, werden auch einsen reingeshiftet.
shifte doch mal 0x7fffffff nach rechts.
Was ist bei dir 'rechts ne 1'
Weil nämlich ein shiften nach rechts:
printf("%X %d\n", 0x7fffffff, 0x7fffffff ); // 7FFFFFFF 2147483647
printf("%X %d\n", 0x7fffffff >> 1, 0x7fffffff >> 1 ); // 3FFFFFFF 1073741823die im Kommentar angegebene Ausgabe liefert, also im Prinzip keine neuen Erkenntnisse
-
proggingmania schrieb:
pale dog schrieb:
wenn rechts 'ne 1 ist, werden auch einsen reingeshiftet.
shifte doch mal 0x7fffffff nach rechts.
Was ist bei dir 'rechts ne 1'
äääh, vertan, ich meinte 'links'
-
proggingmania schrieb:
Das ist ein Widerspruch.
Das könnte daran liegen, dass ~0 nicht undefiniert ist. Nur unspezifiziert, aber zu 99,9% gleich -1. Was undefiniert ist, ist -1 nach rechts zu shiften. Ich wüsste jetzt aber auch kein System, wo das zu echten Problemen führt, auf einem normalen PC wird da ein arithmetischer Shift durchgeführt, und das ergibt dann eben wieder -1.
-
Bashar schrieb:
Nur unspezifiziert, aber zu 99,9% gleich -1. Was undefiniert ist, ist -1
Bei meinem Compiler ist es so, das
printf("%d\n", UINT_MAX == ~0 );
printf("%d\n", -1 == ~0 );Beides eine wahre Aussage liefert,
also ~0 zu 100% positiv
und
~0 zu 100% negativ ist.
Im Falle des shiftens scheint er sich dann wohl lieber für den negativen Fall zu entscheiden.
Wenn man ihn mit kucke mal ich bin unsigned überzeugt:
(unsigned int) ~0 << 1
dann funzt das
-
Bashar schrieb:
Ich wüsste jetzt aber auch kein System, wo das zu echten Problemen führt ..
Das System ist der Inhalt meines Wirsings( Rübe, Omme, Kopf
),
das versucht hat groovmasters MSB Invertierung nachzuvollziehen.
Dachte mir erst, ha !, das unsigned int casting kann man auch weglassen aber
Pustekuchen
Wusste eben nicht, das der Compiler von Haus aus von rechts einsen nachschiebt der Hund, dachte shiften nach rechts zieht immer Nullen nach.
-
proggingmania schrieb:
Bei meinem Compiler ist es so, das
printf("%d\n", UINT_MAX == ~0 );
printf("%d\n", -1 == ~0 );
Beides eine wahre Aussage liefert,
also ~0 zu 100% positiv
und
~0 zu 100% negativ ist.das ist kein widerspruch.
die x^y verschiedenen kombinationen eines datenworts werden für unterschiedliche zahlenbereiche benutzt. im einen fall von 0...UINT_MAX (vorzeichenlos) und von INT_MIN...INT_MAX (mit vorzeichen). dabei kommt's vor, dass die selbe bitkombination mehrere bedeutungen hat.
proggingmania schrieb:
Wusste eben nicht, das der Compiler von Haus aus von rechts einsen nachschiebt der Hund, dachte shiften nach rechts zieht immer Nullen nach.
es gibt auch programmmiersprachen (z.b. Java) mit zwei rechts-shift operatoren. einer schiebt nullen rein und einer einsen. da ist dann nix undefiniert
-
proggingmania schrieb:
Bei meinem Compiler ist es so, das
printf("%d\n", UINT_MAX == ~0 );
printf("%d\n", -1 == ~0 );Beides eine wahre Aussage liefert,
also ~0 zu 100% positiv
und
~0 zu 100% negativ ist.Du musst die Datentypen und Konvertierungen bedenken. Beim ersten Vergleich wird ~0 von int nach unsigned int umgewandelt.
-
Bashar schrieb:
Du musst die Datentypen und Konvertierungen bedenken. Beim ersten Vergleich wird ~0 von int nach unsigned int umgewandelt.
Das scheint den Compiler nicht so zu kratzen, weil der auch
printf("%d\n", UINT_MAX == (int)~0 );
als wahr ansieht.
Aber das ist ja auch ok.
~0 ist halt beides, -1 und UINT_MAX.Mein Problem war halt die Unwissenheit, das negative Zahlen nach dem Rechtsshiften von links einsen nachziehen.
-
proggingmania schrieb:
Das scheint den Compiler nicht so zu kratzen, weil der auch
printf("%d\n", UINT_MAX == (int)~0 );
als wahr ansieht.Ich wüßte auch nicht, warum ihn das kratzen sollte, wenn du den int ~0 nochmal nach int castest, bevor er nach unsigned konvertiert wird.
-
Bashar schrieb:
Ich wüßte auch nicht, warum ihn das kratzen sollte, wenn du den int ~0 nochmal nach int castest, bevor er nach unsigned konvertiert wird.
Der kann sich doch nicht einfach erdreisten, meinen nach (int) gecasteten Wert wieder intern nach ( unsigned int ) zurückzuwandeln ? Mit welchem Recht ?
-
proggingmania schrieb:
Bashar schrieb:
Ich wüßte auch nicht, warum ihn das kratzen sollte, wenn du den int ~0 nochmal nach int castest, bevor er nach unsigned konvertiert wird.
Der kann sich doch nicht einfach erdreisten, meinen nach (int) gecasteten Wert wieder intern nach ( unsigned int ) zurückzuwandeln ? Mit welchem Recht ?
Mit den Integer-Promotions-Regeln. Siehe C-Standard
-
proggingmania schrieb:
Der kann sich doch nicht einfach erdreisten, meinen nach (int) gecasteten Wert wieder intern nach ( unsigned int ) zurückzuwandeln ? Mit welchem Recht ?
Siehe rüdiger, aber nochwas dazu: Es interessiert ihn nicht, ob du irgendwas gecastet hast. Er sieht einen Vergleich zwischen unsigned int und int, und um den durchführen zu können, muss er beide Seiten auf einen gemeinsamen Typ bringen. Das ist in dem Fall eben unsigned int.