mikrocontroller.net

Forum: Compiler & IDEs Strukturpointer Warnmeldung | Sammlung von Strings in Array


Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe 2 Probleme mit einem Programm von mir.

Zum einen erstelle ich einen Pointer:
struct strEntry {
  unsigned char mode;
  void (*Operate_Func)(void);
};


struct strMainMenue{
  unsigned char Entries;
  struct strEntry MenEntry[8];
};


struct strMainMenue *ptrMenue = &MainMenue; 

(Der Pointer ist Global)
Hier gibt er mir ne Warnung mit
"warning: initialization discards qualifiers from pointer target type"

Ich verstehe nicht ganz warum er das macht?

----------------

Meine zweite Frage dreht sich um eine Sammlung von Strings in einem 
Array:

Hier habe ich mir angelesen, dass man dies wie folgt macht:
const unsigned char arrMainMenue[7][8] =
{"","","","","","EINSTELL","ZURUECK"};

Hier gibt er mit die Warnung:
"warning: excess elements in array initializer"
"warning: (near initialization for 'arrMainMenue')"

Dies verstehe ich auch nicht.
Wird die Stringsammlung etwa nicht mit arrMainMenue[Anzahl der 
Strings][maximale Stringlänge] erezugt?

Hoffe meine Frage ist kurz und verständlich rübergekommen. Vielen Dank 
für eure Hilfe :)

Grüße Marcel

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:

> Ich verstehe nicht ganz warum er das macht?

Weil du uns die Deklaration von MainMenue schuldig geblieben bist.  Die
hat nämlich offenbar noch einen type qualifier (const oder volatile,
restricted kann es hier nicht sein), den du mit deiner Zuweisung
wegwirfst.  Genau das sagt dir der Compiler ja auch.

(Davon abgesehen ist nicht klar, warum du den Zeiger überhaupt hast,
wenn offenbar MainMenu selbst ja auch eine globale Variable ist.
Davon kannst du mit & immer die Adresse bilden.)

> Dies verstehe ich auch nicht.
> Wird die Stringsammlung etwa nicht mit arrMainMenue[Anzahl der
> Strings][maximale Stringlänge] erezugt?

Wird sie, aber der String "EINSTELL" ist nicht 8 Zeichen lang sondern
9.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Weil du uns die Deklaration von MainMenue schuldig geblieben bist.

Oh entschuldige. Das hatte ich ganz vergessen zu posten
const struct strMainMenue MainMenue =
{
  .Entries = 7,
  .MenEntry =
  {
    {//Verbrauch 'Einstellungen'
     .mode    = 0,
     .Operate_Func = &Go_Into_Settings,
    },  
    
    {......
    }

  }
};


Jörg Wunsch schrieb:
> Wird sie, aber der String "EINSTELL" ist nicht 8 Zeichen lang sondern
> 9.

Oh nein, natürlich die '\0' hatte ich vergessen - wie peinlich :(...

Merci beaucoup für deine schnelle Antwort :)

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:

> const struct strMainMenue MainMenue =
  *****

Da haben wirs schon


> Jörg Wunsch schrieb:
>> Wird sie, aber der String "EINSTELL" ist nicht 8 Zeichen lang sondern
>> 9.
>
> Oh nein, natürlich die '\0' hatte ich vergessen - wie peinlich :(...

Wobei das eigentlich zulässig wäre :-)
Wenn der String ohne den abschliessenden '\0' exakt in das 
bereitgestellte Array passt, dann darf der Compiler den abschliessenden 
'\0' nicht drannhängen.

Hättest du arrMainMenue[7][7] definiert, wär es eine 
Initialisierungsüberschreitung.


(Wie sinnvoll diese Regel ist, sei dahingestellt. Aber von der Sorte 
gibts noch ein paar mehr in C)

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> dann darf der Compiler den abschliessenden
> '\0' nicht drannhängen.

Das kann dann doch aber gefährlich werden, weil ich dann ja nicht mehr 
das Ende des Strings detektiere - da nehme ich lieber 8*1Byte mehr :)

Danke für eure Antworten!

Grüße
Marcel

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Karl heinz Buchegger schrieb:
>> dann darf der Compiler den abschliessenden
>> '\0' nicht drannhängen.
>
> Das kann dann doch aber gefährlich werden, weil ich dann ja nicht mehr
> das Ende des Strings detektiere - da nehme ich lieber 8*1Byte mehr :)
>

Ändern sich eigentlich die Texte zur Laufzeit?
Wenn nicht, dann ist das die bevorzugte Variante
const char * arrMainMenue[] =
 {"","","","","","EINSTELL","ZURUECK"};

Kein Vertun bei der Zählerei und das bischen mehr Speicherverbrauch für 
die Pointer wird durch die Einsparung bei den Texten mehr als wett 
gemacht.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ändern sich eigentlich die Texte zur Laufzeit?

Nett von dir das du nochmal nachfragst. Nein die Texte ändern sich 
nicht. Das ist ein Array zur Menüführung. Wie du siehst haben die ersten 
5 Einträge keinen "Namen". Man sieht hier sofort den entprechenenden 
Wert, wie zum Beispiel die Uhrzeit.
const char * arrMainMenue[] =
 {"","","","","","EINSTELL","ZURUECK"};

Was genau ist denn hier anders, als meine Schreibweise? Ist das ein 
Pointer, der wiederum auf einen Pointer zeigt?

Grüße Marcel

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:

>
> const char * arrMainMenue[] =
>  {"","","","","","EINSTELL","ZURUECK"};
> 
>
> Was genau ist denn hier anders, als meine Schreibweise? Ist das ein
> Pointer, der wiederum auf einen Pointer zeigt?


Deines erzeugt das hier
   arrMainMenue
   +---+---+---+---+---+---+---+---+---+
   |\0 |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+
   |\0 |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+
   |\0 |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+
   |\0 |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+
   |\0 |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+
   | E | I | N | S | T | E | L | L |\0 |
   +---+---+---+---+---+---+---+---+---+
   | Z | U | R | U | E | C | K |\0 |   |
   +---+---+---+---+---+---+---+---+---+

Die andere Lösung erzeugt das hier
   arrMainMenue
   +------+                       +---+
   |   o------------------------->|\0 |
   +------+                       +---+      +---+
   |   o------------------------------------>|\0 |
   +------+                       +---+      +---+
   |   o------------------------->|\0 |
   +------+                       +---+      +---+
   |   o------------------------------------>|\0 |
   +------+                       +---+      +---+
   |   o------------------------->|\0 |
   +------+                       +---+
   |   o-----------+
   +------+        |     +---+---+---+---+---+---+---+---+---+
   |   o  |        +---->| E | I | N | S | T | E | L | L |\0 |
   +---|--+              +---+---+---+---+---+---+---+---+---+
       |
       |       +---+---+---+---+---+---+---+---+
       +------>| Z | U | R | U | E | C | K |\0 |
               +---+---+---+---+---+---+---+---+


Wobei der Compiler auch noch alle Pointer auf den \0 String zu einem 
einzigen String zusammenlegen kann und es den \0 String dann effektiv 
nur einmal gibt.

In der Verwendung sind aber beide Versionen so gut wie identisch. Erst 
wenn alles ins Flash ausgelagert wird, zeigt sich der tatsächliche 
Unterschied (weil dann der C eigene Array - Pointer Zusammenhang nicht 
mehr greift). Das ist aber halb so schlimm.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow vielen Dank,
für den Tipp :)
Den werde ich gleich mit einfließen lassen

Du hast dir echt viel Mühe mit dem Zeichnen gemacht :)

Grüße Marcel

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.