Forum: Mikrocontroller und Digitale Elektronik Casting: was mache ich falsch?


von Maxim B. (max182)


Lesenswert?

Liebes Forum,
ich habe eine Frage:
ich möchte aus Array in Flash Array in RAM füllen. Dabei ist Flash-Array 
als char und Ram-Array als int. Code:
1
static const signed char ged_16[512] PROGMEM = {
2
0,2,4,6,8,10,12,14,16,18,20,21,23,25,27,28,
3
30,31,33,34,36,37,38,39,40,41,42,43,44,45,45,46,
4
47,47,48,48,48,49,49,49,49,50,50,50,50,50,50,50,
5
50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,
6
49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
7
50,50,50,50,50,50,50,50,50,50,50,50,50,50,49,49,
8
49,49,49,49,49,49,49,48,48,48,48,48,48,47,47,47,
9
47,47,47,46,46,46,46,46,46,46,46,45,45,45,45,45,
10
45,45,45,45,45,45,46,46,46,46,46,46,46,46,47,47,
11
47,47,47,47,48,48,48,48,48,48,49,49,49,49,49,49,
12
49,49,49,50,50,50,50,50,50,50,50,50,50,50,50,50,
13
50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
14
49,49,49,49,49,49,49,49,50,50,50,50,50,50,50,50,
15
50,50,50,50,50,50,50,50,49,49,49,49,48,48,48,47,
16
47,46,45,45,44,43,42,41,40,39,38,37,36,34,33,31,
17
30,28,27,25,23,21,20,18,16,14,12,10,8,6,4,2,
18
0,-2,-4,-6,-8,-10,-12,-14,-16,-18,-20,-21,-23,-25,-27,-28,
19
-30,-31,-33,-34,-36,-37,-38,-39,-40,-41,-42,-43,-44,-45,-45,-46,
20
-47,-47,-48,-48,-48,-49,-49,-49,-49,-50,-50,-50,-50,-50,-50,-50,
21
-50,-50,-50,-50,-50,-50,-50,-50,-50,-49,-49,-49,-49,-49,-49,-49,
22
-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,
23
-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-49,-49,
24
-49,-49,-49,-49,-49,-49,-49,-48,-48,-48,-48,-48,-48,-47,-47,-47,
25
-47,-47,-47,-46,-46,-46,-46,-46,-46,-46,-46,-45,-45,-45,-45,-45,
26
-45,-45,-45,-45,-45,-45,-46,-46,-46,-46,-46,-46,-46,-46,-47,-47,
27
-47,-47,-47,-47,-48,-48,-48,-48,-48,-48,-49,-49,-49,-49,-49,-49,
28
-49,-49,-49,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
29
-50,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,-49,
30
-49,-49,-49,-49,-49,-49,-49,-49,-50,-50,-50,-50,-50,-50,-50,-50,
31
-50,-50,-50,-50,-50,-50,-50,-50,-49,-49,-49,-49,-48,-48,-48,-47,
32
-47,-46,-45,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-34,-33,-31,
33
-30,-28,-27,-25,-23,-21,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2
34
};
1
int tabform[512] = {0};
2
3
        int *y;
4
  y = tabform;
5
  for(int x=0;x<512;x++){
6
    *y += (int)pgm_read_byte (&ged_16[x]);
7
    y++;  
8
  }

Ergebnis: solange ich zu negativen Zahlen komme, steht in Array statt 
wie erwartet -2, -4, -6 ( 0xFFFE, 0xFFFC, 0xFFFA ) einfach 254, 252, 250 
( 0x00FE, 0x00FC, 0x00FA ).
D.h. Problem liegt in casting. Aber wo ich Fehler mache, konnte ich 
nicht capieren. Ich habe schon versucht, casting in 2 Schritten zu 
machen, zuerst eine Zwischenvariable als signed char, dann eine 
Zwischenvariable als int, erst danach in Array - immer gleiche 
Ergebnis...

AVR Studio 4.18 und gcc-5.4.0.

Vielen Dank für die Erklärung im voraus!

von Bernd K. (prof7bit)


Lesenswert?

caste das vorzeichenlose byte zuerst mal in ein signed char. Erst dann 
hast Du eine negative Zahl.

von Maxim B. (max182)


Lesenswert?

Danke!
Ich habe nun verstanden, wo mein Fehler lag...
Ich habe auch die Variante mit Zwischenvariable char ausprobiert. Aber 
ich ging davon aus, daß char signed ist.
1
int *y;
2
  char xx;
3
  y = tabform;
4
  for(int x=0;x<512;x++){
5
    xx = (char)pgm_read_byte (&ged_16[x]);
6
    *y += (int)xx;
7
    y++;  
8
  }
Das war mein Fehler!

Die Variante
1
  int *y;
2
  signed char xx;
3
  y = tabform;
4
  for(int x=0;x<512;x++){
5
    xx = (signed char)pgm_read_byte (&ged_16[x]);
6
    *y += (int)xx;
7
    y++;  
8
  }
 arbeitet wie erwartet.

Vielen Dank!

Beitrag #5094546 wurde von einem Moderator gelöscht.
von Bernd K. (prof7bit)


Lesenswert?

Maxim B. schrieb:
> int *y;
>     *y += (int)xx;

Du brauchst das xx übrigens danach nicht mehr nochmal explizit nach int 
zu casten. Wenn Du ein signed char und ein int addierst wird die ganze 
Rechnung automatisch mit int ausgeführt, beide Operanden werden zuvor 
automatich nach int promoted oder falls größer als int dann zum größten 
Datentyp der in dem Ausdruck vorkommt, mindestens jedoch zu int oder 
falls alle unsigned sind dann zu unsigned int. Stichwort zum Googeln: 
Integer-Promotion.

Und am Rande, falls Du mal drüberstolperst, behalte auch im Hinterkopf 
daß auf dem AVR ein int 16 Bit lang ist, auf größeren Platformen meist 
32 Bit.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Maxim B. schrieb:
1
 static const __flash int8_t ged_16[512] = { ... };
2
  int tabform[512] = {0};
3
  int *y = tabform;
4
  for (int x = 0; x < 512; x++)
5
    {
6
      *y += ged_16[x];
7
      y++;
8
    }

von Besetzungsexperte (Gast)


Lesenswert?

> Casting: was mache ich falsch?
Du hast nicht die Couch genutzt.

von Maxim B. (max182)


Lesenswert?

Vielen Dank Bernd! Ich muß noch vieles lernen...

von Rolf M. (rmagnus)


Lesenswert?

Maxim B. schrieb:
> Danke!
> Ich habe nun verstanden, wo mein Fehler lag...
> Ich habe auch die Variante mit Zwischenvariable char ausprobiert. Aber
> ich ging davon aus, daß char signed ist.

Leider ist es in C nicht wie bei allen anderen Integer-Typen so, dass es 
automatisch signed ist, wenn nichts explizit davor steht. Es ist vom 
Compiler und dessen Einstellungen abhängig. Es gibt dann drei als 
verschieden zu betrachtende Typen: char, signed char und unsigned char. 
Ersteres nimmt man für Text, während man für Binärdaten immer die beiden 
letzteren verwendet.

von fop (Gast)


Lesenswert?

Und da unter C noch nicht mal die Anzahl der Bits eines Variablentyps 
festgelegt sind, bindet man noch besser die Datei stdint.h ein und 
benutzt deren Typen.
Bei uint8_t ist dann alles klar.

von Maxim B. (max182)


Lesenswert?

fop schrieb:

> Bei uint8_t ist dann alles klar.
Nur bei AVR Studio 4 weniger bequem, weil diese Typen nicht automatisch 
von Programm beim Schreiben blau gemacht werden. Das bringt mehr Gefahr, 
Fehler zu machen. Nur aus diesem Grund bleibe ich bei gewöhnlichen 
Typen.

AVR Studio 4 ist weit von Vollkommenheit. Z.B. hier ist gar nicht 
möglich, in Watch-Fenster die Variablen uint24_t zu beobachten, die bei 
heutigem GCC längst möglich sind. Aber einfache IDE, für AVR 
ausreichend, aus IDE kann man Programm direkt in Mikrocontroller 
schreiben... Bequem...

von Bernd K. (prof7bit)


Lesenswert?

fop schrieb:
> Und da unter C noch nicht mal die Anzahl der Bits eines Variablentyps
> festgelegt sind, bindet man noch besser die Datei stdint.h ein und
> benutzt deren Typen.
> Bei uint8_t ist dann alles klar.

Und wenn man schreibfaul ist wie ich macht man es wie die ehrwürdigen 
Kernelhacker und macht sich typedefs nach dem Vorbild in linux/types.h

u8
s8
u16
s16
u32
s32
u64
s64

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.