www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeiger auf Stringarray


Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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):
#include <stdio.h>

#define __flash
#define unsigned

enum
{
  english,
  deutsch,
  maxSprachen // immer letzter Eintrag
};

__flash unsigned char *strings[][maxSprachen] =
  {
    { "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)


int  aktuelleSprache = english;
//int  aktuelleSprache = deutsch;

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

    __flash unsigned char  *text;

    unsigned char b;
    signed char a;
  } diestruct_t;

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


  puts( "Variante 1:" );
  puts( s.text );
}


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

    __flash unsigned char  **text;

    unsigned char b;
    signed char a;
  } diestruct_t;

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


  puts( "Variante 2:" );
  puts( s.text[aktuelleSprache] );
}

int main( int nargs, char **args )
{
  variante1();
  variante2();

  return 0;
}

Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also Variante 2 ist es, die Sprache wird erst bei der Ausgabe verwendet.

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

Der Compiler will es so:
__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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss beim Testen einen Fehler gemacht haben, die Strings liegen nun in 
einer Struktur
__flash unsigned char *stringsNeu[][maxSprachen]

die Struktur passt auch
  typedef struct xxx
  {
     __flash unsigned char  **text;

    unsigned char b;
    signed char a;
  } 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ganze wird fest angelegt, daher auch im Flash:
__flash const diestruct_t arr[] = {
                    { stringsNeu[1],1,2 },  
  { stringsNeu[2],3,4 },  
  { stringsNeu[3],4,5 },  
  { stringsNeu[4],5,6 },  
};  

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Halt!

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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht das typedef für diestruct_t aktuell aus? Es scheint irgendwie
anders als bei Klaus zu sein.

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

und
  typedef struct
  {
    __flash unsigned char  * __flash *text;
    unsigned char b;
    signed char a;
  } diestruct_t;

Damit sollten nicht nur die Strings, sondern auch das Array mit den
Zeigern auf dieselben im Flash abgelegt werden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   _flash unsigned char * ptr;     // das worauf der Ptr zeigt ist im flash
   unsigned char * _flash ptr;     // der Ptr selbst ist im Flash, nicht
                                   // aber die Daten auf die er zeigt
   _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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

> ...

Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein
__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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?)

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Klaus23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe nun eine eigene Demo-Anwendung geschrieben die das Problem 
eingrenzt:
Das ganze ist nun sehr vereinfacht.

Das geht:
#include <ioavr.h>
#include <intrinsics.h>
#include <stdbool.h>

__flash unsigned char  string[] = "a";

typedef struct xxx
{
  __flash unsigned char  *text; 

  unsigned char b;
} yyy;

yyy z= {  string ,2} ;

int main( void )
{
  return 0;
}


Das geht nicht:
#include <ioavr.h>
#include <intrinsics.h>
#include <stdbool.h>

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

typedef struct xxx
{
  __flash unsigned char  *text; 

  unsigned char b;
} yyy;

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


int main( void )
{
  return 0;
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.