Casting: was mache ich falsch?

OP #5094510
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!
OP #5094533
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.
#5094582
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.
#5094988
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.
OP #5095831
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...
#5101138
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

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