PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kurze Frage zu C-Operatoren


BAGZZlash
2011-07-26, 21:41:58
Muss gerade etwas Code verstehen, habe aber ein bisschen Probleme mit der Operator-Arithmetik:


#define UL unsigned long
#define UC unsigned char

UL a
a = ((a << 1) | 1) ^ (UL) byte;

"<<" ist ein Bitshift nach links. Was aber bedeutet "| 1"?
Anschließend noch das Ergebnis "^ (UL) byte"? Was bedeutet das? Das Ergebnis der ersten großen Klammer "hoch" a und davon nur die ersten acht Bits oder wie?

Bin für jeden Hinweis dankbar. :smile:

Sephiroth
2011-07-26, 21:57:09
| Bitwise OR
^ Bitwise XOR
"(foo) bar" ist ein type cast nach foo der variable bar

das ein variablen typ gecasted wird, kenn ich aber auch nicht :freak:

BAGZZlash
2011-07-26, 22:26:42
Okay, super, vielen Dank. Also das Ergebnis nach den Operationen ist dann ein Byte, also nur die ersten (rechten) acht Bits?

Beispiel:


a = 0xF9828305 = 11111001100000101000001100000101b

Schritt 1 - Bitshift eins nach links: a = a << 1 => a = 11110011000001010000011000001010b

Schritt 2 - Sicherstellen, dass ganz rechts 'ne Eins steht: a = a | 1 => a = 11110011000001010000011000001011b

Schritt 3 - Bitweise xor: a ^ (ursprüngliches a) => 11110011000001010000011000001011b xor 11111001100000101000001100000101b = 00001010100001111000010100001110b = 0xA87850E

Davon die ersten acht Bits sind 00001110b = 0x0E.


So?

/edit: Nein, ich hab' falsch geparsed. Neuer Versuch:



a = 0xF9828305 = 11111001100000101000001100000101b

Schritt 1 - Bitshift eins nach links: a = a << 1 => a = 11110011000001010000011000001010b

Schritt 2 - Sicherstellen, dass ganz rechts 'ne Eins steht: a = a | 1 => a = 11110011000001010000011000001011b

Schritt 3 - Typecast vom ursprünglichen a, Typ UL nach a, Typ byte: Ursprüngliches a hat den Wert 11111001100000101000001100000101b => (UL) byte = 00000101b (nehme nur die rechten acht Bits)

Schritt 4 - Bitweise xor mit Ergebnis aus Schritt 3: a ^ (Schritt 3) => 11110011000001010000011000001011b xor 00000000000000000000000000000101b = 11110011000001010000011000001110b = 0xF305060E


Richtig?

huha
2011-07-26, 23:51:37
byte ist kein Typ, sondern ein Variablenname.

-huha

ShadowXX
2011-07-26, 23:59:26
| Bitwise OR
^ Bitwise XOR
"(foo) bar" ist ein type cast nach foo der variable bar

das ein variablen typ gecasted wird, kenn ich aber auch nicht :freak:
Da wird auch kein variablen typ gecasted, sondern byte (eine variable wie huha schon anmerkte) wird auf unsigned long gecasted (UL ist ja per #define ein unsigned long. der compiler ersetzt beim compilieren ja einfach das UL mit unsigned long (genauso wie er das UC durch unsigned char ersetzt)).

Sephiroth
2011-07-27, 00:01:56
byte ist kein Typ, sondern ein Variablenname.

-huha
Da wird auch kein variablen typ gecasted, sondern byte (eine variable wie huha schon anmerkte) wird auf unsigned long gecasted (UL ist ja per #define ein unsigned long).
hehe, stimmt, alles andere würde auch kein sinn machen. stand nur nirgends das byte eine variable ist und da dachte ich eben an den typ byte. ;)

Gast
2011-07-27, 01:32:13
((foo << 1 ) | 1) = 2 * foo + 1
das ganze dann xor mit einer anderen Variablen.
D.h die resultierende Zahl erhält genau an den Stellen eine 1, wenn foo und byte unterschiedliche Bitwerte haben, sonst 0.

huha
2011-07-27, 01:46:11
hehe, stimmt, alles andere würde auch kein sinn machen. stand nur nirgends das byte eine variable ist und da dachte ich eben an den typ byte. ;)

Gibt halt keinen Typ byte. Manche Compiler mögen das vielleicht haben, es ist aber keineswegs verbreitet. 8 bit breite Werte sind üblicherweise (unsigned) char.

-huha

BAGZZlash
2011-07-27, 07:38:55
Danke an alle! :smile:(y)

Hm, jetzt muss ich rausfinden, womit diese "byte"-Variable gefüllt wird (ist aber auch ein blöder Variablenname). Leider habe ich den Code von darüber nicht bzw. "byte" wird meiner Funktion von außen übergeben und ich habe den Code nicht, der die Funktion aufruft. Bei "a" konnte ich mir das ja noch denken, aber...

Trotzdem vielen Dank!

Misda
2011-07-27, 10:42:52
Was ich ja nicht verstehe:

Warum programmieren Leute so? Das ist doch nie im Leben wartbar. Wenn man sich das in ein paar Wochen wieder anschaut, muss man sich erst mühsam wieder reindenken.

Wahrscheinlich hat es ja "Performance" Gründe - aber ernsthaft: Sollte ein guter Compiler nicht das gleiche hinbekommen?

BAGZZlash
2011-07-27, 11:08:59
Was ich ja nicht verstehe:

Warum programmieren Leute so? Das ist doch nie im Leben wartbar. Wenn man sich das in ein paar Wochen wieder anschaut, muss man sich erst mühsam wieder reindenken.

Wahrscheinlich hat es ja "Performance" Gründe - aber ernsthaft: Sollte ein guter Compiler nicht das gleiche hinbekommen?
Das denke ich auch, ein Compiler macht auch aus 2x + 1 solche logischen Operationen, die dann schneller sind. Selbst programmieren muss man so nicht.

Exxtreme
2011-07-27, 11:11:46
Was ich ja nicht verstehe:

Warum programmieren Leute so? Das ist doch nie im Leben wartbar. Wenn man sich das in ein paar Wochen wieder anschaut, muss man sich erst mühsam wieder reindenken.

Wahrscheinlich hat es ja "Performance" Gründe - aber ernsthaft: Sollte ein guter Compiler nicht das gleiche hinbekommen?
Das ist C. :D

Da wurde darauf geachtet möglichst kurz und komprimiert schreiben zu können.

Trap
2011-07-27, 11:27:28
Das ist problemlos lesbar, wenn man mit Bit-Verarbeitung vertraut ist. Wenn nicht, wäre auch bessere Notation nicht hilfreich.

Misda
2011-07-27, 11:49:04
Das ist problemlos lesbar, wenn man mit Bit-Verarbeitung vertraut ist. Wenn nicht, wäre auch bessere Notation nicht hilfreich.

Ich bin damit ein wenig vertraut - aber trotzdem würde ich sowas nie schreiben :)

Ich bin einfach kein Fan davon. Jemand der kleine Stellen so programmiert, hört bei komplexen Funktionen nicht damit auf. An der Stelle kann es dann meiner Meinung nach sehr haarig werden, wenn man sich das Zeug nach Wochen/Monaten mal wieder anschaut (ist ja meist auch nicht toll kommentiert :wink:).

huha
2011-07-27, 12:39:50
Wie willst du das sonst programmieren?
Wir wissen halt nicht, was die Funktion machen soll, aber das liegt daran, daß wir nur eine einzige Zeile sehen und keine Ahnung vom Rest des Programms haben.

Dort wird was bitweise gemacht, also benutzt man auch bitweise Operatoren.
Derjenige, der das ernsthaft als

(2*a + 1) ^ byte

schreiben will, gehört erschossen, weil es ultraunübersichtlich ist. Hier wird ja nicht gerechnet, sondern ein Bitstring entsprechend formatiert, damit er nachher vernünftig verXORt werden kann.

-huha

Tiamat
2011-07-27, 12:43:10
LOL das ist definitiv Code of the month ^^
Aber der Gast hat recht, das ist 2x +1 xor andere variable.
Spontan fällt mir dazu ein, dass man mit Xor einen Wertetausch von Zahlen mit 2 Operation statt 3 hinbekommt. Dazu passt auch der Datentyp int. Vielleicht war das die Absicht davon, aber man sieht hier zu wenig Code.

Was den Compiler angeht, das glaub ich nicht. Das lässt sich auch mit beliebigen Programmen zeigen, dass die Verwendung von Bitshiftung zum Rechnen manchmal sogar hunderte von Prozent ausmacht ggü. Operatoren und natürlich auch ggü. API-Methoden.
Das ist ja selbst auf Assemberebene so: Man kann ein Register leer machen mit CLR EAX oder wie auch immer. Oder man kann es mit XOR EAX, EAX. Dadurch spart man jeweils ein oder mehrere Bytes.

Exxtreme
2011-07-27, 13:06:10
Was den Compiler angeht, das glaub ich nicht. Das lässt sich auch mit beliebigen Programmen zeigen, dass die Verwendung von Bitshiftung zum Rechnen manchmal sogar hunderte von Prozent ausmacht ggü. Operatoren und natürlich auch ggü. API-Methoden.
Das ist ja selbst auf Assemberebene so: Man kann ein Register leer machen mit CLR EAX oder wie auch immer. Oder man kann es mit XOR EAX, EAX. Dadurch spart man jeweils ein oder mehrere Bytes.
Das ist korrekt, dass Bitshift ganze Größenordnungen schneller sein kann als eine Operation. Andererseits sind Compiler auch so schlau zu erkennen, dass man einen Bitshift nutzen kann anstatt einer Multiplikation und benutzen dann den Bitshift auch wenn im Sourcecode eine Multiplikation steht.

BAGZZlash
2011-07-27, 13:44:02
Das ist problemlos lesbar, wenn man mit Bit-Verarbeitung vertraut ist. Wenn nicht, wäre auch bessere Notation nicht hilfreich.



Ich bin damit ein wenig vertraut - aber trotzdem würde ich sowas nie schreiben :)

Zustimm: Ich bin auch mit Bitoperationen vertraut, aber nicht mit der Notation.

@Trap: Ich verstehe Deine Aussage nicht so ganz. Chinesische Zeichen sind problemlos lesbar, wenn man chinesisch kann. Wenn nicht, macht auch Deutsch keinen Sinn? Oder wie ist das gemeint?

Marscel
2011-07-27, 14:18:23
Ich bin damit ein wenig vertraut - aber trotzdem würde ich sowas nie schreiben :)

Hm? Wenn ich mir überlege, wo ich das überall brauche - fern von Hardware und Optimierungen: Rechtebits, gespeicherte IP-Adressen, Binärinhalt aus Dateien, Statemarker, ... bevor man sich da Integerarithmetik ausdenkt, ist man mit Bitoperationen deutlich schneller am Ziel.

Sinnvoll ist natürlich immer, einen Kommentar davor zu schreiben, was das ganze denn soll.

Trap
2011-07-27, 14:48:49
@Trap: Oder wie ist das gemeint?
Hilft dir die Variante in der alles ausgeschrieben ist wirklich:
a=a.leftShift(1).binaryOr(1).binaryXor(byte.toUnsignedLong());

BAGZZlash
2011-07-27, 14:52:58
Hilft dir die Variante in der alles ausgeschrieben ist wirklich:
a=a.leftShift(1).binaryOr(1).binaryXor(byte.toUnsignedLong());

Ach so ist das gemeint. Äh, ja, hilft mir tatsächlich.

noid
2011-07-28, 00:00:26
Das ist C. :D

Da wurde darauf geachtet möglichst kurz und komprimiert schreiben zu können.

Das ist problemlos lesbar, wenn man mit Bit-Verarbeitung vertraut ist. Wenn nicht, wäre auch bessere Notation nicht hilfreich.

"Das haben wir schon immer so gemacht".

Alleine für das "UL" würde ich dem "Programmierer" schon androhen, dass bei Wiederholung eine weisse Kuh geschächtet wird.
Sry, aber es gibt fucking editoren für autovervollständigung. Der Code ist somit Quark - egal ob und was er macht.
Bitoperationen sollten einem schon klar sein, aber die Darstellung ist mangelhaft.

Trap
2011-07-28, 00:09:57
Sry, aber es gibt fucking editoren für autovervollständigung.
Aber für ein "Sorry" und Großbuchstaben reicht es nicht? :tongue:

Das #define kann man problemlos nachträglich ändern, ausgeschriebene Typnamen nicht. Wenn man das machen möchte, sollte man es allerdings nicht UL nennen :wink:

noid
2011-07-28, 00:15:36
Aber für ein "Sorry" und Großbuchstaben reicht es nicht? :tongue:

Das #define kann man problemlos nachträglich ändern, ausgeschriebene Typnamen nicht. Wenn man das machen möchte, sollte man es allerdings nicht UL nennen :wink:

Das erinnert mich, dass ich eigentlich nen "Spellchecker" nicht nur für meine Beiträge sondern auch für C-Code (also den des Teams) bräuchte.