Das Tutorial ist offenbar für eine CPU geschrieben, die über 16 Bit int
verfügt und 2-er Komplementdarstellung benutzt.
Regel 1 in C: gerechnet wird immer mindestens im Datentyp int.
D.h. 1 << 15 ist erstmal eine int Angelegenheit. Was passiert hier?
Eine binäre 1
0b0000000000000001
wir dum 15 POsition nach links verschoben
0b1000000000000000
wie ist der Datentyp des Ergebnisses?
Er ist int, weil die ursprüngliche 1 ebenfalls int war.
WICHTIG: int ist signed, hat also ein Vorzeichen.
Da der Compiler offenbar 2-er Komplement benutzt (wie praktisch alle
C-Compiler), bedeutet dieses Bitmuster durch das gesetzte MSB, das es
sich hier um eine negative Zahl handelt.
Wie geht es weiter in der C-Anweisung
reg_32 = .......
Es erfolgt also eine Zuweisung an reg_32. Rechts vom = steht ein
Ausdruck dessen Datentyp int (also 16-Bit, signed) ist, links vom =
steht der Datentyp uint32_t, also 32 Bit - unsigned.
Damit die Zuweisung erfolgen kann, müssen die Datentypen aneinander
angeglichen werden. Aus dem signed 16 BIt muss ein unsigned 32 BIt
werden.
Wie geschieht das?
Zunächst wird die Bitzahl angepasst. D.h. die 16 Bit werden auf 32 Bit
erweitert.
Und jetzt passierts!
Die 16 Bit Zahl, da negativ, kann nicht einfach links mit 0-en gepimpt
werden. Das negative Vorzeichen muss erhalten bleiben und die negative
Zahl muss als solche erhalten bleiben. Wenn man ein wenig mit 2-er
Komplement rumspielt, kommt man drauf, dass die Regel so aussieht: Links
werden Bits angehängt, ob die 0 oder 1 sind, entscheidet das MSB. Ist es
1, dann müssen links auch 1 Bit angehängt werden.
Und so wird aus
0b10000000000000000
bei der Erweiterung auf 32 Bit
0b111111111111111111000000000000000
oder eben in Hex 0xFF80
Man kann es nicht oft genug betonen: Bei Bit- und Byte Manipulationen
ist immer unsigned der Datentyp mit dem man zum Ziel kommt! Lässt man
dem Compiler diesen Punkt offen, dann nimmt er stillscheigend signed an,
womit dann die Probleme anfangen und gegebenenfalls muss man eben bei
Zahlenkonstanten mit einem Suffix für Klarheit sorgen.
(Ich hab die fehlende Lösung 1U<<15 im Tutorial noch hinzugefügt. Sie
wäre IMHO eigentlich die richtige Lösung gewesen. Das 1L << 15 ist ja
genauso unsinnig, wie es auch 1LL << 15 ist. Beide 'Lösungen' schieben
ja das 'Problem' wieder nur soweit vor sich her, dass es sich nicht
auswirkt)