Forum: Compiler & IDEs Problem im Tutorial


von LearningByDoing (Gast)


Lesenswert?

Hallo,
ich arbeite gerade das C Tutorial durch doch leider hänge ich an einem 
Punkt fest:
1
#define MEINBIT15 15
2
#define MEINBIT42 42
3
 
4
uint32_t reg_32; /* uint32_t definiert per typedef z. B. in stdint.h */
5
uint64_t reg_64; /* uint64_t definiert per typedef z. B. in stdint.h */
6
 
7
reg_32 |= (1 << MEINBIT15);              /* FEHLER: Setzt die Bits 31 - 15, da ((int)1 << 15) == 0xFFFF8000 */
8
 
9
reg_32 |= ((uint32_t)1 << MEINBIT15);    /* Hier wird nur Bit 15 gesetzt. */
10
reg_32 |= (1L << MEINBIT15);             /* andere Schreibweise. */
11
reg_64 |= (1LL << MEINBIT42);            /* Hier wird nur Bit 42 gesetzt,
12
                                            andere Schreibweise für 64 Bit (long long). */

Bzw. an:
1
/* FEHLER: Setzt die Bits 31 - 15, da ((int)1 << 15) == 0xFFFF8000 */
könnte mir das vlt. jmd mit anderen Worten erklären warum Bit 31-15 
gesetzt werden?

Ich bedanke mich schon einmal im Vorraus

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Das wirkt wie aus dem Kontext gerissen.

Mit

  reg_32 |= (1 << MEINBIT15);

setzt Du Bit 15 im vorher enthaltenen Wert für reg_32. Probiere
dochmal, reg_32 vorher einen Wert zuzuweisen, zB

  reg_32 = 0;
  reg_32 |= (1 << MEINBIT15);

von LearningByDoing (Gast)


Lesenswert?

Hallo,
danke für die schnelle Antwort,
ich verstehe leider immernoch nicht so ganz was die in dem
Tutorial meinen mit:

"FEHLER: Setzt die Bits 31 - 15"

von LearningByDoing (Gast)


Lesenswert?

Edit:
Ich habe das von dieser Seite:

http://www.mikrocontroller.net/articles/Bitmanipulation

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Achso ....

Mal Dir das mal binär auf, dann siehst Du es.

von Karl H. (kbuchegg)


Lesenswert?

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)

von LearningByDoing (Gast)


Lesenswert?

Hallo,

danke für die gute und ausfürliche Erklärung :)

Das hat mir wirklich sehr weiter geholfen.

Ich wünsche noch einen schönen Sonnntag

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.