uint32_treg_32;/* uint32_t definiert per typedef z. B. in stdint.h */
5
uint64_treg_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|=(1U<<MEINBIT15);/* */
11
reg_32|=(1L<<MEINBIT15);/* andere Schreibweise. */
12
reg_64|=(1LL<<MEINBIT42);/* Hier wird nur Bit 42 gesetzt,
13
andere Schreibweise für 64 Bit (long long). */
Wenn ich das richtig verstanden habe, haben MEINBIT15 und MEINBIT 42
jeweils uint8_t. Dies haben in disem Beispiel den wert von 15 und 42.
Bei 8 Bit können dise höchstens den Wert von 0-255 annnehmen.
Wenn ich beide Zahlen zusammen fassen möchte muss ich da nicht
schreiben:
1
uint16_treg16|=8<<MEINBIT15
damit verschienbe ich in reg16 (mit 16 Bit) MEINBIT15 um 8 Stellen nach
links und kann anschliessend MEINBIT42 dazunehmen.
1
reg16|=MEINBIT42
Damit habe ich jetzt in reg16 als höchstes Bit MEINBIT15 zu stehen und
als tiefstes Bit MEINBIT42.
Im Beispiel gibt es auch reg_32. Ich kann als Beispiel auch 4 Zahlen mit
8 Bit in reg_32 zusammen führen.
Versteh ich das richtig so?
>uint16_t reg16 |= 8<<MEINBIT15
ist zu groß für 16Bit
du hast nur 16 Stellen. Wenn du die 8(binär 1000) 15 stellen nach links
schiebst purzelt sie links raus
Karl schrieb:> Wenn ich das richtig verstanden habe, haben MEINBIT15 und MEINBIT 42> jeweils uint8_t.
Nein!
Das Zauberwort heißt "Integer Promotion". Der resultierende Datentype
ist also eher int, als uint_8
Karl schrieb:> haben MEINBIT15 und MEINBIT 42> jeweils uint8_t.
Genaugenommen haben die erstmal garkleinen type.
Der Preprocessor macht da eine einfache Textersetzung und erst beim
späteren Compilieren wird dann was konkretes daraus:
z.B.: aus "reg_64 |= (1LL << MEINBIT42);" wird "reg_64 |= (1LL << 42);"
usw.
>#define MEINBIT15 15>#define MEINBIT42 42
dise defines solltest du nur in Verbindung mit
1<<MEINBITyx
verwenden.
>reg16 |= MEINBIT42
macht garantiert nicht das wass du denkst.
Im Moment bringt ihr mich ganz schön durcheinander.
uint32_t reg_16 = ((MEINBIT15 << 8) | MEINBIT42);
Habe noch mal alles (versucht) zu lesen. Hab da wohl was verwechselt.
Sieht das besser aus und funktioniert so?
Hab es einfach aus dem AVR GCC ... übernommen.
Soll eine uint mit 32 Bit (reicht auch 16 Bit) und 2 x 8 Bit Variablen
sein.
Der Name ist eigentlich egal
MEINBIT15 ist 15(dezimal), 1111 binär. F (hex)
wenn du jetzt
MEINBIT15 << 8 machst
erhälst du
1111 0000 0000 binär.
Ich glaube du verwechselst hier Grundlegende Schreibweisen.
Eine (in der AVR-Welt) gebräuchliche Darstellung ist diese 1<<Anzahl
_Stellen
In einer anderen Welt nutzt man da ehr 0x8000 für Bit 15.
Tip:
Scheib dir die Zahlen erst mal binär hin.
Die Operation << schiebt die linke Seite um rechte Seite Stellen nach
links.
Aus deiner 1<<MEINBIT15 wird also:
0000 0000 0000 0001(die eins)
1000 0000 0000 0000(15 mal nach links)
deine_Variable |= 1<<MEINBIT15
bewirkt, das das 15Bit gesetzt, alle anderen unverändert sind:
1xxx xxxx xxxx xxxx
uint32_t reg_16 = ((MEINBIT15 << 8) | MEINBIT42);
(MEINBIT15 << 8) ist 1111 0000 0000 binär
MEINBIT42 ist 0010 1010 binär
reg_16 ist dann also 0000 0000 0000 0000 0000 1111 0010 1010 binär.
Gewollt hattest du aber Warscheinlich Bit 42 und Bit 15 gesetzt.
Geht nicht, weil dein reg_16 nur 32 Bit hat.
Hallo Karl,
1)
#define MEINBIT 32
ist nur ein define, das ist ein eigenes Thema, und verwirrt hier nur. Du
müsstest erstmal verstehen was ein Define ist. Hier egal.
2)
Ebenso ungünstg für einen Einstig ist diese Kurzschreibweise:
reg |= x;
Auch unleserlich und verwirrend, dort steht eigentlich:
reg = reg | x;
3)Dann gleich alles zusammen mischen, verwirrt noch mehr, erstmal
langsam anfangen
uint8_t a=0, b=1;
a=b<<3;
In b steht 0000 0001
In a danach 0000 1000
VG
Dennis
Karl schrieb:> Der Name ist eigentlich egal
Nein!
Ist er nicht.
Deine Namensgebung ist an der Stelle verwirrend. Somit macht es das
Quelltext Verständnis schwieriger. Dieser Thread soll allerdings dein
Verständnis "schärfen", darum ist jede Art von Verwirrung
kontraproduktiv.
Sorgfalt und Disziplin mindern Verwirrungen!
Lesetipp: "Clean Code"
Regel fürs Verständnis, und typisches Missverständnis: Bei
a = b <op> c
ist der Typ von a für die Auswertung von b<op>c völlig irrelevant. Erst
das Resultat davon wird in den Typ von a konvertiert.
Somit wird 1<<15 als "int" ausgewertet, und liefert bei einer 16-Bit
Kiste ein gesetztes Vorzeichenbit, also negativ. Die gleiche Operation
bei einer 32-Bit Kiste liefert ein positives Ergebnis.
Arduino Fanboy D. schrieb:> Lesetipp: "Clean Code"
#define MEINBIT15 15
#define MEINBIT42 42
main ()
{
uint32_t reg_32 = ((MEINBIT15 << 8) | MEINBIT42);
....
}
Das ist das gleich wie in der Quelle ich ich hatte.
Dabei wird in der Variable reg32 mit 32 Bit die Variable MEINBIT15 nach
linls verschoben um 8 Stellen (MSB Stelle 15 bis 8), danach wird
MEINBIT42 auf die Stelle LSB Stelle 7 bis 0 gesetzt.
(prx) A. K. schrieb:> Eherne Regel fürs Verständnis: Bei> a = b <op> c> ist der Typ von a für die Auswertung von b<op>c völlig irrelevant. Erst> das Resultat davon wird in den Typ von a konvertiert.>> Somit wird 1<<15 als "int" ausgewertet, und liefert bei einer 16-Bit> Kiste ein gesetztes Vorzeichenbit, also negativ. Die gleiche Operation> bei einer 32-Bit Kiste liefert ein positives Ergebnis.
Sorry, das versteh ich nicht.
Karl schrieb:>> Eherne Regel fürs Verständnis: Bei>> a = b <op> c>> ist der Typ von a für die Auswertung von b<op>c völlig irrelevant. Erst>> das Resultat davon wird in den Typ von a konvertiert.>>>> Somit wird 1<<15 als "int" ausgewertet, und liefert bei einer 16-Bit>> Kiste ein gesetztes Vorzeichenbit, also negativ. Die gleiche Operation>> bei einer 32-Bit Kiste liefert ein positives Ergebnis.>> Sorry, das versteh ich nicht.
Es geht z.B. um
> reg_32 |= (1 << MEINBIT15);
a = reg_32 # ist vom Typ uint32_t
b = 1 # ist vom Typ int
c = 15 # ist vom Typ int
Gerechnet wird also zuerst 1<<15 als int<<int, und das ergibt bei einer
8/16-Bit CPU -32768. Das wird danach in 32-Bit konvertiert und behält
dabei diesen Wert.
Verbreitetes Missverständnis bei Anfängern: Sie gehen fälschlicherweise
davon aus, dass sich aus dem Typ von reg_32 die Breite der gesamten
Rechnung ergibt.
> Somit wird 1<<15 als "int" ausgewertet, und liefert bei einer 16-Bit> Kiste ein gesetztes Vorzeichenbit, also negativ. Die gleiche Operation> bei einer 32-Bit Kiste liefert ein positives Ergebnis.
16_Bit_signed: 0x8000
Erweitert auf 32Bit: 0xFFFF 8000 (das Vorzeichenbit wird in alle
Höherwetigen Bits kopiert)
16_Bit_unsigned: 0x8000
Erweitert auf 32Bit: 0x0000 8000
Arduino Fanboy D. schrieb:> Karl schrieb:>> Wenn ich das richtig verstanden habe, haben MEINBIT15 und MEINBIT 42>> jeweils uint8_t.>> Nein!
Soweit hast du recht.
> Das Zauberwort heißt "Integer Promotion". Der resultierende Datentype> ist also eher int, als uint_8
Der Grund ist nicht Integer Promotion, sondern die Typermittlung
lexikalischer Integer-Konstanten. Und da ist eine 1 per Sprachdefinition
vom Typ "int". Eine Schreibweise für einfach hingeschriebene ganzzahlige
Konstanten kleiner als "int" gibts nicht.
Karl schrieb:> Sorry, das versteh ich nicht.
Das sind aber C und C++ Grundlagen.
Lese bitte das Kapitel über numerische Literale, integer Promotion und
über die Wirkung der Operatoren. Zudem das Kapitel über implizite Casts,
welche auch bei Zuweisungen zu tragen kommen.
(prx) A. K. schrieb:> Der Grund ist nicht Integer Promotion, sondern die Typermittlung> lexikalischer Integer-Konstanten.
Von mir aus...
Karl schrieb:> #define MEINBIT15 15> #define MEINBIT42 42> main ()> {> uint32_t reg_32 = ((MEINBIT15 << 8) | MEINBIT42);> ....> }
Du rechnest (15<<8)|42. Interessant, und ergibt 3882, hat ber nichts mit
Bit Nummer 15 und auch nichts mit Bit Nummer 42 zu tun ...
LG, Sebastian
(prx) A. K. schrieb:> Verbreitetes Missverständnis bei Anfängern: Sie gehen fälschlicherweise> davon aus, dass sich aus dem Typ von reg_32 die Breite der gesamten> Rechnung ergibt.
Die Variable reg_32 hat eine Grösse von 32 Bit. Dabei steht in der MSB
die Zahl 15 und in der LSB die Zahl 42.
Kann ich diese Zahlen auch wieder zurückholen?