Forum: Mikrocontroller und Digitale Elektronik Zeiger auf Stringarray


von Klaus23 (Gast)


Lesenswert?

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?

von Klaus W. (mfgkw)


Lesenswert?

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
}

von Klaus23 (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

Was heißt "Der Compiler will es so"?
Wer ist hier der Meister, du oder der Compiler?

von Klaus23 (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

hm, ich könnte jetzt raten, wie die Initialisierung aussieht.
Ich kann es mir aber auch sparen und warten, bis du deinen
Quelltext herzeigst.

von Klaus23 (Gast)


Lesenswert?

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
};

von Klaus W. (mfgkw)


Lesenswert?

Ich sehe so keinen Fehler.
Allerdings glaube ich auch nicht, hier die ganze Wahrheit zu sehen.
Insbesondere passt auch die Fehlermeldung nicht so recht dazu.

von Klaus W. (mfgkw)


Lesenswert?

Halt!

Ich sehe gerade, daß du die struct ja auch ins Flash packst.
Muss das sein?

von yalu (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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.

> ...

von Klaus23 (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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?)

von yalu (Gast)


Lesenswert?

> 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 :)

von Klaus23 (Gast)


Lesenswert?

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
}

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.