Forum: Mikrocontroller und Digitale Elektronik Schiebebefehl in C


von Schieber (Gast)


Lesenswert?

Hallo zusammen,

hab folgendes Problem.
Ich will in einen "unsigned long" einzelne Bits setzen.

vereinfacht etwa so:
1
unsigned_long a;
2
unsigned_char b; 
3
a != (1<<b);


Funktioniert alles ganz gut bis b größer als 16 wird. Wieso warnt mich 
dann der Compiler mit dieser Meldung?

left shift count >= witdh of type

Wenn ich das richtig verstehe warnt er mich, dass ich über die Länge von 
a hinaus schiebe, oder verstehe ich das falsch? Aber a ist doch 32 Bit 
lang, oder hab ich nen Denkfehler.
Bin noch nicht so fit in C, also haut mich nicht gleich.

Danke.

von Peter II (Gast)


Lesenswert?

Schieber schrieb:
> Aber a ist doch 32 Bit
> lang, oder hab ich nen Denkfehler.

a ja, aber die 1 nicht.

a != ( (uint32_t)1<<b);

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

1
a |= (1L<<b);

von Schieber (Gast)


Lesenswert?

Ok das stimmt! Die 1 ist keine 32 Bit breit. Aber wieso stört das?
Den Typecast verstehe ich, aber was hat das L zu bedeuten?

Danke

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Google mal nach:
c const L

von Karl H. (kbuchegg)


Lesenswert?

Schieber schrieb:
> Ok das stimmt! Die 1 ist keine 32 Bit breit. Aber wieso stört das?

weil es bei der Berechnung eines Ausdrucks erst einmal scheissegal ist, 
was links vom = steht

Erst wird der Ausdruck berechnet, dann wird nachgesehen, was mit dem 
Ergebnis des Ausdrucks weiter passieren soll.


  float i;

  i = i * ( 3 + 5 );


das (3 + 5) wird als INteger berechnet, weil 3 ein int ist und 5 ein int 
ist.
Das das Ergebnis dieser Addition dann auf float 'angehoben' werden muss, 
damit man multiplizieren kann, ist eine Geschichte, die unabhängig von 
der Addition ist.

von Dominik S. (dasd)


Lesenswert?

Schieber schrieb:
> Aber wieso stört das?

Naja, es stört genau aus dem Grund den dir der Compiler ja auch schon 
genannt hat :)
(Die Fehlermeldung von oben)

Schieber schrieb:
> left shift count >= witdh of type

Der Compiler nimmt für die 1 ein Integer (16 bit breit).
Schiebst du jetzt mehr als 16 mal rüber schiebst du die 1 wieder aus der 
Variable raus.

Schieber schrieb:
> Den Typecast verstehe ich, aber was hat das L zu bedeuten?

Das sagt dem Compiler, dass er die 1 als Long anlegen soll.
Mit 1F würde es z.B. ein Float werden.

von Schieber (Gast)


Lesenswert?

Super danke an alle.
Wieder was gelernt.

Ich habs schon probiert es geht mit dem Cast und mit dem L.

Danke.

von Schieber (Gast)


Lesenswert?

Es wäre dann auch so gegangen. Sehe ich das richtig?
1
unsigned_long a;
2
unsigned_long b; 
3
a != (1<<b);

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Schieber schrieb:
> Es wäre dann auch so gegangen. Sehe ich das richtig?
>
>
1
> unsigned_long a;
2
> unsigned_long b;
3
> a != (1<<b);

Da wäre ich mir nicht sicher, da 1 dann nach wie vor ein normales "int" 
ist.

(Ich vermute, dass die Unterstriche zwischen "unsigned" und "long" nicht 
in deinem Programm stehen und dass das Ausrufezeichen ein Strich 
(Oder-Operator) sein soll.)

von Karl H. (kbuchegg)


Lesenswert?

Schieber schrieb:
> Es wäre dann auch so gegangen. Sehe ich das richtig?
>
>
1
> unsigned_long a;
2
> unsigned_long b;
3
> a != (1<<b);
4
>

Nein.
Du sollst die Dinge nicht 'richtig sehen', sondern in einem Buch 
nachlesen. Bei Schiebeoperationen

    a << b

bestimmt der Datentyp von a, und zwar nur der Datentyp von a, wie die 
Operation implementiert wird.
Macht auch Sinn. Denn der Datentyp von b ist für alle notwendigen 
praktischen Zwecke selbst mit einem uint8_t mehr als groß genug. Es ist 
das a, welches geschoben wird und wie die Operation implementiert wird, 
hängt einzig und alleine von diesem a ab. Das b ist nur MIttel zum Zweck

von Schieber (Gast)


Lesenswert?

Markus W. schrieb:
> (Ich vermute, dass die Unterstriche zwischen "unsigned" und "long" nicht
> in deinem Programm stehen und dass das Ausrufezeichen ein Strich
> (Oder-Operator) sein soll.)

Ja so ist es.
Ich habs einfach nochmal getippt und dann zusätzlich Fehler rein 
gebracht.
Ich hab mich beim Tippen wieder selbst überholt.

Danke.

von Schieber (Gast)


Lesenswert?

Ok dann so.

unsigned long a;
unsigned long b;
unsigned long c = 1;
a |= (c<<b);

von Karl H. (kbuchegg)


Lesenswert?

Machs einfach

   c |= ( 1UL << b);

und gut ists.
Das ist die in C vorgesehene Schreibweise und es gibt keinen Grund, sie 
nicht zu verwenden.

(In der Praxis möchtest du auf einem AVR sowieso keine Variable an der 
Stelle b haben. Da versucht man das sowieso durch andere Dinge zu 
ersetzen, was auch meistens gelingt)

von Schieber (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> (In der Praxis möchtest du auf einem AVR sowieso keine Variable an der
> Stelle b haben. Da versucht man das sowieso durch andere Dinge zu
> ersetzen, was auch meistens gelingt)


Das stimmt!
Ihr habt recht. Ich mach es richtig.

Danke an alle.

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.