Schiebebefehl in C

Gast #2783120
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.
#2783150
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.
#2783159
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.
(Firma: guloshop.de) #2783172
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.)
#2783174
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
Gast #2783175
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.
#2783180
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren