Zeiger auf Stringarray

Gast #1440907
Für eine mehrsprachige Display-Anzeige habe ich folgendes Speicher Array 
definiert (Compiler IAR für AVR):

__flash unsigned char strings[][maxSprachen][LAENGE] = {
{ "go",      "los" },
{ "Info",      "Info" },
{ "Push",      "drücken" }
};

In einer Strucktur möchte ich nun auf die Strings zugreifen. Und dort 
anhand der aktuellen Sprache den jeweiligen Text anzeigen. Die 
Anzeigefunktion hat diesen Prototyp:
void show_text(unsigned char __flash *t)


typedef struct xxx
{
  __flash unsigned char  *text[LAENGE]; // geht net !
  __flash unsigned char  **text; // geht auch net ! aber wie dann?

  unsigned char b;
  signed char a;
};

Wie muss der Zeiger auf ds mehrspaltige string Array aussehen?
Ich weiß jetzt nicht so recht, ob beim Initialisieren der struct
je nach dann aktueller Sprache ein Text ausgewählt werden soll
(Variante 1), oder ob über die struct ein Text in allen Sprachen
erreichbar sein soll, und erst bei der Ausgabe über die Sprache
entschieden wird, welcher genommen werden soll (Variante 2).

Beides geht (__flash und unsigned mal wegdefiniert, damit ich es
auf dem PC probieren kann):
1
#include <stdio.h>
2

3
#define __flash
4
#define unsigned
5

6
enum
7
{
8
  english,
9
  deutsch,
10
  maxSprachen // immer letzter Eintrag
11
};
12

13
__flash unsigned char *strings[][maxSprachen] =
14
  {
15
    { "go",      "los" },
16
    { "Info",      "Info" },
17
    { "Push",      "drücken" }
18
  };
19

20
// In einer Strucktur möchte ich nun auf die Strings zugreifen. Und dort
21
// anhand der aktuellen Sprache den jeweiligen Text anzeigen. Die
22
// Anzeigefunktion hat diesen Prototyp:
23
// void show_text(unsigned char __flash *t)
24

25

26
int  aktuelleSprache = english;
27
//int  aktuelleSprache = deutsch;
28

29
// Variante 1:
30
// in der struct wird genau ein Text hinterlegt; beim Initialisieren je
31
// nach Sprache und Nummer des Textes anzugeben:
32
void variante1()
33
{
34
  typedef struct xxx
35
  {
36
    //__flash unsigned char  *text[LAENGE]; // geht net !
37
    //__flash unsigned char  **text; // geht auch net ! aber wie dann?
38

39
    __flash unsigned char  *text;
40

41
    unsigned char b;
42
    signed char a;
43
  } diestruct_t;
44

45
  diestruct_t  s = { strings[2/* 2 fuer Druecken */][aktuelleSprache], 0, 0 };
46

47

48
  puts( "Variante 1:" );
49
  puts( s.text );
50
}
51

52

53
// Variante 2:
54
// in der struct wird fuer jede Sprache ein Text hinterlegt; beim
55
// Initialisieren Nummer des Textes anzugeben, dagegen die Sprache
56
// erst bei der Ausgabe:
57
void variante2()
58
{
59
  typedef struct xxx
60
  {
61
    //__flash unsigned char  *text[LAENGE]; // geht net !
62
    //__flash unsigned char  **text; // geht auch net ! aber wie dann?
63

64
    __flash unsigned char  **text;
65

66
    unsigned char b;
67
    signed char a;
68
  } diestruct_t;
69

70
  diestruct_t  s = { strings[2/* 2 fuer Druecken */], 0, 0 };
71

72

73
  puts( "Variante 2:" );
74
  puts( s.text[aktuelleSprache] );
75
}
76

77
int main( int nargs, char **args )
78
{
79
  variante1();
80
  variante2();
81

82
  return 0;
83
}
Gast
Also Variante 2 ist es, die Sprache wird erst bei der Ausgabe verwendet.

Die String-Struktur lässt sich nicht so anlegen:
1
__flash unsigned char *strings[][maxSprachen];

Der Compiler will es so:
1
__flash unsigned char strings[][maxSprachen][LAENGE];


Beim anlegen der Struktur dann der Fehler:

Error[Pe144]: a value of type "unsigned char __flash (*)[23]" cannot be 
used to initialize an entity of type "unsigned char __flash **" xx.c 5


... 23 ist die LAENGE
Gast
Muss beim Testen einen Fehler gemacht haben, die Strings liegen nun in 
einer Struktur
1
__flash unsigned char *stringsNeu[][maxSprachen]

die Struktur passt auch
1
  typedef struct xxx
2
  {
3
     __flash unsigned char  **text;
4

5
    unsigned char b;
6
    signed char a;
7
  } diestruct_t;

aber beim füllen mit Daten kommt die Fehlermeldung:

Error[Pe144]: a value of type "unsigned char *__flash *" cannot be used 
to initialize an entity of type "unsigned char __flash **" xx.c 5
Gast
Das ganze wird fest angelegt, daher auch im Flash:
1
__flash const diestruct_t arr[] = {
2
                    { stringsNeu[1],1,2 },  
3
  { stringsNeu[2],3,4 },  
4
  { stringsNeu[3],4,5 },  
5
  { stringsNeu[4],5,6 },  
6
};
Gast
Wie sieht das typedef für diestruct_t aktuell aus? Es scheint irgendwie
anders als bei Klaus zu sein.

Und probier mal folgendes:
1
__flash unsigned char * __flash stringsNeu[][maxSprachen] = {
2
  ...
3
};

und
1
  typedef struct
2
  {
3
    __flash unsigned char  * __flash *text;
4
    unsigned char b;
5
    signed char a;
6
  } diestruct_t;

Damit sollten nicht nur die Strings, sondern auch das Array mit den
Zeigern auf dieselben im Flash abgelegt werden.
Klaus Wachtler schrieb:
> Halt!
>
> Ich sehe gerade, daß du die struct ja auch ins Flash packst.
> Muss das sein?

Würde ich für vernünftig halten.
Allerdings müssen dann die _flash richtig verteilt sein.
Es gibt immerum die alte Frage: Wer ist denn nun im _flash? Das worauf 
der Pointer zeigt, der Pointer selbst oder etwa beide
1
   _flash unsigned char * ptr;     // das worauf der Ptr zeigt ist im flash
2
   unsigned char * _flash ptr;     // der Ptr selbst ist im Flash, nicht
3
                                   // aber die Daten auf die er zeigt
4
   _flash unsigned char * _flash ptr;   // beides ist im Flash


(zumindest wenn IAR __flash als Modifier wie const auffast, wovon ich 
einmal stark ausgehe)

Aber Klaus hat schon recht:
Poste doch bitte endlich einmal einen umfangreicheren Codeabschnitt! Mit 
der Microsicht der Dinge ist es schwer den Überblick zu halten, was du 
denn nun wirklich konkret gemacht hast.
Karl heinz Buchegger schrieb:
> Klaus Wachtler schrieb:
>> Halt!
>>
>> Ich sehe gerade, daß du die struct ja auch ins Flash packst.
>> Muss das sein?
>
> Würde ich für vernünftig halten.

ich eigentlich auch, aber nur, wenn er weiß was er will und es
konsequent durchhält.

Da ich aber nur den gcc habe und er offenbar nicht, steige ich
sowieso aus, was das Probieren angeht.

> ...
Gast
Ein
1
__flash unsigned char * __flash stringsNeu[][maxSprachen] = ...
wird mit
Warning[Pa011]: memory attribute duplicated xxx.c 7
gemeldet.

und beim initialsieren kommt:
Error[Pe144]: a value of type "unsigned char *__flash *" cannot be used 
to initialize an entity of type "unsigned char __flash *__flash *" xxx.c 
5
Bitte, bitte, bitte

Poste mehr Code.
Es bringt nichts, da jetzt immer nur 1 Zeile zu präsentieren mit der 
Fehlermeldung dazu.
Das ganze ist in erster Linie erst mal eine Konzeptfrage! Und mir 
scheint du schmeisst da jetzt 2 Konzepte grossartig durcheinander.

Zuerst muss das Konzept stehen, dann kümmern wir uns darum es dem 
Compiler schmackhaft zu machen. Vorschlag: lass die __flash erst mal 
alle beiseite und lege alles im SRAM ab. Und erst dann gehen Teile der 
Datenstruktur ins Flash


(Ich hab da irgendwas im Hinterkopf, dass bei IAR so etwas

   const char Text = "Hallo Welt";

durch das const sowieso im Flash angelegt wird. Trügt mich da jetzt mein 
Gedächtnis?)
Gast
> Ein
>
> __flash unsigned char * __flash stringsNeu[][maxSprachen] = ...
>
> wird mit
> Warning[Pa011]: memory attribute duplicated xxx.c 7
> gemeldet.

Dann verhält sich — entgegen meiner und Karl Heinz' Vermutung — __flash
anders als die Standard-Qualifier const und volatile in C :-(

Man müsste jetzt also durch Lesen im Handbuch des IAR oder durch Aus-
probieren herausfinden, was __flash genau macht, wann der Compiler
Daten schon von sich aus ins Flash legt usw.

Beides ist für einen Nicht-IAR-User nicht so leicht ;-)

Aber wie Karl Heinz geschrieben hat: Poste mehr Code, der kompilierfähig
ist (ohne die __flash), damit nicht einer nach langen Bemühungen eine
Lösung findet, die am Ende gar nicht deinen Vorstellungen entspricht :)
Gast
Habe nun eine eigene Demo-Anwendung geschrieben die das Problem 
eingrenzt:
Das ganze ist nun sehr vereinfacht.

Das geht:
1
#include <ioavr.h>
2
#include <intrinsics.h>
3
#include <stdbool.h>
4

5
__flash unsigned char  string[] = "a";
6

7
typedef struct xxx
8
{
9
  __flash unsigned char  *text; 
10

11
  unsigned char b;
12
} yyy;
13

14
yyy z= {  string ,2} ;
15

16
int main( void )
17
{
18
  return 0;
19
}


Das geht nicht:
1
#include <ioavr.h>
2
#include <intrinsics.h>
3
#include <stdbool.h>
4

5
__flash unsigned char  *  strings[] = { "a","b","c"};
6

7
typedef struct xxx
8
{
9
  __flash unsigned char  *text; 
10

11
  unsigned char b;
12
} yyy;
13

14
yyy z= {  strings[0] ,2} ;
15
/*
16
fehler in der zeile zuvor:
17
Error[Pe028]: expression must have a constant value D:\test2\main.c 20 
18
*/
19

20

21
int main( void )
22
{
23
  return 0;
24
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.