Forum: Compiler & IDEs warning: left shift count >= width of type


von Peter (Gast)


Lesenswert?

Hallo,

folgende Zeile erzeugt mir die Warnung "warning: left shift count >= 
width of type":
1
unsigned long int file_size = (i2c_get_byte(true) + (i2c_get_byte(true) << 8) + (i2c_get_byte(true) << 16)) + (i2c_get_byte(false) << 24);

Wie kann ich diese Warnung unterdrücken?

Der Code soll im Grunde einfach nur eine 4 Byte breite Zahl aus dem 
I2C-EEPROM lesen und entsprechend zusammensetzen.

lg, Peter

von Thomas B. (detritus)


Lesenswert?

1
unsigned long int file_size = 
2
 (i2c_get_byte(true) +
3
 (i2c_get_byte(true) << 8) + 
4
 (unsigned long int)(i2c_get_byte(true) << 16)) +
5
 (unsigned long int)(i2c_get_byte(false) << 24);

Für den Compiler sind solche Konstrukte erstmal ints (hier wohl 16 bit 
lang). Will man mehr um mehr als 15 schieben, muss man auf einen 
grösseren Typ casten.

Edit: Ok, mein Nachfolger hat recht, man muss alles casten. Was ich 
geschrieben hab, gilt für konstante werte, die beim compilieren 
ausgerechnet werden.

von Sven P. (Gast)


Lesenswert?

wenn i2c_get_byte() als
1
unsigned char i2c_get_byte(...);

vereinbart ist, wird erst mal mit Bytes gerechnet, und die sind nunmal 
acht Bit breit.
Wenn du jetzt
1
(i2c_get_byte(true) << 8)
machst, rechnen wir immer noch mit den 8-Bit breiten Bytes, aber du 
schiebst quasi mit "<<8" bis hin zur 16. Stelle nach links, und das geht 
beim Byte eben nicht.

Lösung: Zwing dem Compiler was Breiteres auf (Casting):
1
unsigned long int file_size =
2
  ((unsigned long int) i2c_get_byte(true) +
3
  ((unsigned long int) i2c_get_byte(true) << 8) +
4
  ((unsigned long int) i2c_get_byte(true) << 16)) +
5
  ((unsigned long int) i2c_get_byte(false) << 24);

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sven Pauli wrote:

> Wenn du jetzt
>
1
> (i2c_get_byte(true) << 8)
2
>
> machst, rechnen wir immer noch mit den 8-Bit breiten Bytes, ...

Nein, machen wir nicht.  Wir rechnen dann mit `int' (aber mit einem
vorzeichenbehafteten!), weil das die integer promotion rules der
Sprache C so verlangen.

von Peter (Gast)


Lesenswert?

Wow, bin wieder einmal beeindruckt von den prompten Antworten hier :-)

Vielen Dank,
jetzt funktioniert alles!

lg, Peter

von Phillip H. (philharmony)


Lesenswert?

Der Beitrag ist zwar schon älter aber ich habe genau das selbe Problem:
Ich habe es so gemacht wie oben beschrieben
1
unsigned long int val =
2
 ((unsigned long int) (*(var->value) << 16)) +
3
 ((unsigned long int) (*((var->value)+1)));
trotzdem bekomme ich die Warnung.
var->value ist int.
AVR-Studio, Optimierung auf -Os

von (prx) A. K. (prx)


Lesenswert?

Phillip Hommel schrieb:

>  ((unsigned long int) (*(var->value) << 16)) +

Stall zugesperrt als das Pferd schon ausgebüchst ist.

von Phillip H. (philharmony)


Lesenswert?

Ah, du meinst daß das Bit-Schieben eine Klammer zu weit "innen" erfolgt?

von Stefan E. (sternst)


Lesenswert?

Phillip Hommel schrieb:

> Ich habe es so gemacht wie oben beschrieben

Nein, hast du nicht. Du musst "*(var->value)" casten, nicht das Ergebnis 
vom Shift.

von Phillip H. (philharmony)


Lesenswert?

Jo, hab den feinen Unterschieb bemerkt.
Danke ;)

von Joachim B. (jojo84)


Lesenswert?

Holla zusammen!

Ich habe auch gerade das oben genannte Problem, aber in einer Abfrage:
1
if( x &= (1<<25) )
2
  {
3
  ;
4
  }
Erklärt sihc ja eigentlich von selbst: x ist ein long und ich will Bit 
25 abfragen.
Aber ich check nicht ganz, wo ich dann casten muß.
Würd mich freuen, wenn mich jemand fix aufklärt :)

VG

von (prx) A. K. (prx)


Lesenswert?

1L<<25

von Joachim B. (jojo84)


Lesenswert?

@ A.K.:
OH!
Das ist ja toll! DANKE!

Kannst du mir vielleicht auch kurz erklären, warum das so ist? einfach 
eintippern ist zwar schön einfach, aber ich würd das gern verstehen :)

VG

von Stefan E. (sternst)


Lesenswert?

Bist du sicher, dass du dort ein "&=" haben möchtest?

von Stefan E. (sternst)


Lesenswert?

Joachim A. schrieb:

> Kannst du mir vielleicht auch kurz erklären, warum das so ist? einfach
> eintippern ist zwar schön einfach, aber ich würd das gern verstehen :)

Weil die 1 sonst nur ein int ist, also 16 Bit groß.

von (prx) A. K. (prx)


Lesenswert?

Joachim A. schrieb:

> Kannst du mir vielleicht auch kurz erklären, warum das so ist? einfach
> eintippern ist zwar schön einfach, aber ich würd das gern verstehen :)

1L ist (long)1

Wenn dir das auch nix nützt, dann solltest du mal einen Blick in ein C 
Handbuch riskieren.

von Joachim B. (jojo84)


Lesenswert?

@Stefan:
Ups, da mit dem "&=" hab ich nicht aufgepasst, danke ;) ...
Und die Erklärung hat auch geholfen. Ich mach jetzt schon ne weile C, 
aber ich hab nie darüber nachgedacht, daß Konstante, wie die 1 da, auch 
int's sind...

Aber ok, wieder was gelernt :)

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.