Forum: Mikrocontroller und Digitale Elektronik SDCC: overflow in implicit constant conversion


von Ralph S. (jjflash)


Lesenswert?

Weil ich immer alles genau wissen mag:

Ausgangssituation:

OS : Slackware Linux
Compiler : SDCC 3.5.0
Zielhardware : STM8S103F3P6

Beim Spielen mit einer 4-stelligen 7-Segmentanzeige bekomme ich 
Compilerwarnung:

      overflow in implicit constant conversion

und weiß nicht warum!

Prototyp wie folgt deklariert:

  void digit4_setall(uint8_t s3, uint8_t s2, uint8_t s1, uint8_t s0);


Ein Aufruf der Funktion mit:

  digit4_setall(0xff, 0xff, ~(0x63), ~(0x39));

produziert die oben genannte Compilerwarnung.

  digit4_setall(0xff, 0xff, 0x9c, 0xc6);

jedoch hingegen nicht.

Warum produziert eine bitweise Negation von 63h (Ergebnis = 9ch) beim 
Aufruf die Warnung, wenn in der Deklaration doch steht, dass es ein 
unsigned char ist )

Mir ist sehr bewusst, dass das höchstwertigste Bit bei der Negation 
gesetzt wird, aber das ist sie bei der Konstanten 9ch aber auch (und bei 
den beiden ffh davor sowieso) ?

von Georg G. (df2au)


Lesenswert?

Zu uint8_t wird die Konstante erst ganz zum Schluss. Davor rechnet der 
Compiler mit Integer, so ist es bei C als Standard definiert.

von Rolf M. (rmagnus)


Lesenswert?

Ralph S. schrieb:
> Warum produziert eine bitweise Negation von 63h (Ergebnis = 9ch) beim
> Aufruf die Warnung, wenn in der Deklaration doch steht, dass es ein
> unsigned char ist )

Was meinst du mit "es"? 0x63 ist vom Typ int. ~0x63 ebenfalls. Wenn du 
das als Parameter an eine Funktion übergibst, wird dieser Wert dann in 
den Parametertyp der Funktion konvertiert. Und da muß dann ein int mit 
dem Wert -100 in einen uint8_t konvertiert werden.

von chris (Gast)


Lesenswert?

Ralph S. schrieb:
> digit4_setall(0xff, 0xff, ~(0x63), ~(0x39));

Mach stattdessen folgendes:
1
digit4_setall(0xff, 0xff, (0x63^0xff), (0x39^0xff));

von Ralph S. (jjflash)


Lesenswert?

... unabhängig davon, dass ich dann jetzt eben die negierten Werte als 
Konstante angebe (und das im Kommentar vermerke) hab ich der beiden 
Beiträge

Rolf M. schrieb:
> Und da muß dann ein int mit
> dem Wert -100 in einen uint8_t konvertiert werden.

Georg G. schrieb:
> Zu uint8_t wird die Konstante erst ganz zum Schluss. Davor rechnet der
> Compiler mit Integer, so ist es bei C als Standard definiert.

wegen das hier gemacht:

digit4_setall(0xff, 0xff, (uint8_t) ~(0x63), (uint8_t) ~(0x39));

Hier wird der Wert vor der Übergabe nach unsigned konvertiert wird 
(allerdings ist mir das ein zu langer Ausdruck und deswegen schreib ich 
gleich die negierten Werte hin )

Vielen Dank an Rolf und Georg

von Friedrich (Gast)


Lesenswert?

Ralph S. schrieb:
> digit4_setall(0xff, 0xff, (uint8_t) ~(0x63), (uint8_t) ~(0x39));
...
> (allerdings ist mir das ein zu langer Ausdruck und deswegen schreib ich
> gleich die negierten Werte hin )

Mir wäre das definitiv zu unleserlich.
Besser wartbar ist sowas:
1
#define SEG_A      0x01
2
#define SEG_B      0x02
3
#define SEG_C      0x04
4
...
5
#define BLANK      ~(0)
6
#define NUM_0      ~(SEG_A + SEG_B + SEG_C + SEG_D + ...)
7
#define NUM_1      ~(SEG_B + SEG_C)
8
...
9
digit4_setall( BLANK, BLANK, NUM_1, NUM_0);

Und noch hübscher bzw. universeller wird es, wenn die Umwandlung auf die 
Segmentcodes in der Funktion verschwindet und man direkt eine Zahl oder 
eine Zeichenkette übergeben kann.

Gruß
Friedrich

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Friedrich schrieb:
> Besser wartbar ist sowas:

Das aber löst nicht das Problem des Threadstarters, denn das Resultat 
von

  ~(SEG_A + SEG_B + SEG_C + SEG_D + ...)

passt wieder nicht in einen uint8_t. Um das zu verhindern, müsste man 
schon

  (~(SEG_A + SEG_B + SEG_C + SEG_D + ...)) & 0xFF

verwenden.

von neuer PIC Freund (Gast)


Lesenswert?

digitsetall.c:
1
#include <stdint.h>
2
3
void digit4_setall(uint8_t s3, uint8_t s2, uint8_t s1, uint8_t s0)
4
{
5
  volatile uint8_t x = 0;
6
  if (s3 == s2)
7
    x += 1;
8
  if (s0 != s1)
9
    x += 3;
10
}
11
12
void main(void)
13
{
14
  digit4_setall(0xff, 0xff, ~(0x63), ~(0x39));
15
}

Welcher Compiler?
1
$ sdcc --version
2
SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8 3.6.3 #9727 (Linux)
3
published under GNU General Public License (GPL)

Noch Fehler?
1
$ sdcc -mstm8 digitsetall.c 
2
digitsetall.c:20: warning 158: overflow in implicit constant conversion
3
digitsetall.c:20: warning 158: overflow in implicit constant conversion

Nö. Nur Warnungen. Allerdings ist der sdcc taufrisch übersetzt.

von Ralph S. (jjflash)


Lesenswert?

Friedrich schrieb:
> Ralph S. schrieb:
>> digit4_setall(0xff, 0xff, (uint8_t) ~(0x63), (uint8_t) ~(0x39));
> ...
>> (allerdings ist mir das ein zu langer Ausdruck und deswegen schreib ich
>> gleich die negierten Werte hin )
>
> Mir wäre das definitiv zu unleserlich.
> Besser wartbar ist sowas:
>
1
> #define SEG_A      0x01
2
> #define SEG_B      0x02
3
> #define SEG_C      0x04
4
> ...
5
> #define BLANK      ~(0)
6
> #define NUM_0      ~(SEG_A + SEG_B + SEG_C + SEG_D + ...)
7
> #define NUM_1      ~(SEG_B + SEG_C)
8
> ...
9
> digit4_setall( BLANK, BLANK, NUM_1, NUM_0);
10
>
>
> Und noch hübscher bzw. universeller wird es, wenn die Umwandlung auf die
> Segmentcodes in der Funktion verschwindet und man direkt eine Zahl oder
> eine Zeichenkette übergeben kann.
>
> Gruß
> Friedrich

Eine Funktion zum direkte setzen hatte ich ja sowieso schon, hier ging 
es schlicht nur darum, einelne Segmente setzen zu können um Bspw. °C auf 
der Anzeige zu sehen. Ansonsten gibt es schon eine


digit4_setdez(int value)


Funktion

Danke an alle noch mal....

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.