Forum: Mikrocontroller und Digitale Elektronik Fehler bei Bitmanipulation


von Horst (Gast)


Lesenswert?

Hallo Leute,
ich bin noch Anfänger im Programmieren und hoffe, dass mir Jemand 
erklären kann, was ich hier falsch mache:
1
unsigned char a,b,c;
2
unsigned short long d;
3
a=0x12;
4
b=0x34;
5
d=0x56;
6
d=((a<<16) |(b<<8) | c);
Eigentlich möchte die 3 Char zu einer Long Variablen zusammenbasteln, 
sodass in d=0x123456 ist. Beim (a<<16) scheint aber etwas nicht zu 
funktionieren. Kann ich nicht so weit verschieben?? Ich programmieren 
einen PIC12F1840 (8 Bit) und benutzte den HIGH_TECH Compiler und MPLAB.

von Falk B. (falk)


Lesenswert?

@  Horst (Gast)

>unsigned char a,b,c;
>unsigned short long d;

Was ist ein short long?

>sodass in d=0x123456 ist. Beim (a<<16) scheint aber etwas nicht zu
>funktionieren.

Klasischer Fehler. Mach es mal so.

1
d=(((long)a <<16) | ((long)b<<8) | c);

von Horst (Gast)


Lesenswert?

Falk Brunner schrieb:
> Was ist ein short long?
Das ist eine 24 Bit Variable. Habe ich aus dem Manuel vom HIGH_TECH 
Compiler.
Vielen Dank für die Hilfe, jetzt klappt es! Ich war sogar schon ganz nah 
dran mit:
1
d=(((long)(a <<16() | ((long)(b<<8)) | c);
Aber da habe ich die Klammern falsch gesetzt und die Convertierung erst 
gemacht, als bereits Werte abgeschnitten wurden.

Was mich noch wundert, ist dass ich ein Char um 8 bin verschieben kann, 
ohne dass etwas abgeschnitten wird, sobald ich es aber um 12 Bit 
verschiebe, klappt es nicht mehr. Hier kommt also wie erwartet y = 0x 00 
00 12 00 raus
1
unsigned char x;
2
unsigned long y;
3
x=0x12;
4
y=x<<8;
Hier dagegen kommt y = 0x 00 00 20 00 raus, die 1 wird abgeschnitten.
1
x=0x12;
2
y=x<<12;
Aber das soll mich nicht weiter stören. Vielen Dank!

von Karl H. (kbuchegg)


Lesenswert?

Horst schrieb:

> Was mich noch wundert, ist dass ich ein Char um 8 bin verschieben kann,
> ohne dass etwas abgeschnitten wird,

Das ist nicht weiter verwunderlich.

In C gilt die Regel:
Gerechnet wird grundsätzlich immer mindestens mit int (bei dir also mit 
16 Bit) als der kleinsten Einheit.
Der Compiler kann, wenn er nachweisen kann dass sich das Ergebnis nicht 
ändert, auf 8 Bit optimieren, aber das ist eine Optimierung, d.h. er 
muss es nicht machen.
Was er aber machen muss, ist sich an den C-Standard zu halten. Und der 
schreibt int als kleinste Einheit bei Rechenoperationen (und Schieben 
ist auch nichts anderes) vor.

d.h.
    a << b

ist grundsätzlich mindestens eine int Operation, selbst dann, wenn a ein 
8 Bit Datentyp ist. (Der Datentyp von b spielt in dieser Operation keine 
Rolle)

> sobald ich es aber um 12 Bit
> verschiebe, klappt es nicht mehr.

Klar. Jetzt knallst du links über die 16 Bit deines 
int-Zwischenergebnisses raus.

> Aber das soll mich nicht weiter stören.

Falsche Einstellung. Du musst dich fragen: Was steckt da dahinter? Ist 
das vom C-Standard so definiert oder ist das etwas was mein Compiler so 
macht, weil ihm der C-Standard dazu die Freiheit lässt. Das sind relativ 
wichtige Punkte, zu wissen, welches Verhalten garantiert ist (und daher 
auf allen C-Compilern gleich funktioniert) und was nicht garantiert ist.

von Horst (Gast)


Lesenswert?

Ach so ist das! Vielen Dank für die gute Erklärung!

Karl Heinz Buchegger schrieb:
>> Aber das soll mich nicht weiter stören.
>
> Falsche Einstellung. Du musst dich fragen: Was steckt da dahinter?

Da hast du eigentlich Recht. Das sind nur so Dinge, die sehr schwer 
sind, alleine herauszufinden. Geht mir jedenfalls so. Darum umso mehr 
Dank für die Erklärung! :)

von dummschwaetzer (Gast)


Lesenswert?

mach es doch mit einer union

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.