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


von Marcel (Gast)


Lesenswert?

Hallo zusammen,

ich habe 2 Probleme mit einem Programm von mir.

Zum einen erstelle ich einen Pointer:
1
struct strEntry {
2
  unsigned char mode;
3
  void (*Operate_Func)(void);
4
};
5
6
7
struct strMainMenue{
8
  unsigned char Entries;
9
  struct strEntry MenEntry[8];
10
};
11
12
13
struct strMainMenue *ptrMenue = &MainMenue; 
14
15
(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:
1
const unsigned char arrMainMenue[7][8] =
2
{"","","","","","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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Marcel (Gast)


Lesenswert?

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

Oh entschuldige. Das hatte ich ganz vergessen zu posten
1
const struct strMainMenue MainMenue =
2
{
3
  .Entries = 7,
4
  .MenEntry =
5
  {
6
    {//Verbrauch 'Einstellungen'
7
     .mode    = 0,
8
     .Operate_Func = &Go_Into_Settings,
9
    },  
10
    
11
    {......
12
    }
13
14
  }
15
};

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

von Karl H. (kbuchegg)


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)

von Marcel (Gast)


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

von Karl H. (kbuchegg)


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
1
const char * arrMainMenue[] =
2
 {"","","","","","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.

von Marcel (Gast)


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.
1
const char * arrMainMenue[] =
2
 {"","","","","","EINSTELL","ZURUECK"};

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

Grüße Marcel

von Karl H. (kbuchegg)


Lesenswert?

Marcel schrieb:

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


Deines erzeugt das hier
1
   arrMainMenue
2
   +---+---+---+---+---+---+---+---+---+
3
   |\0 |   |   |   |   |   |   |   |   |
4
   +---+---+---+---+---+---+---+---+---+
5
   |\0 |   |   |   |   |   |   |   |   |
6
   +---+---+---+---+---+---+---+---+---+
7
   |\0 |   |   |   |   |   |   |   |   |
8
   +---+---+---+---+---+---+---+---+---+
9
   |\0 |   |   |   |   |   |   |   |   |
10
   +---+---+---+---+---+---+---+---+---+
11
   |\0 |   |   |   |   |   |   |   |   |
12
   +---+---+---+---+---+---+---+---+---+
13
   | E | I | N | S | T | E | L | L |\0 |
14
   +---+---+---+---+---+---+---+---+---+
15
   | Z | U | R | U | E | C | K |\0 |   |
16
   +---+---+---+---+---+---+---+---+---+

Die andere Lösung erzeugt das hier
1
   arrMainMenue
2
   +------+                       +---+
3
   |   o------------------------->|\0 |
4
   +------+                       +---+      +---+
5
   |   o------------------------------------>|\0 |
6
   +------+                       +---+      +---+
7
   |   o------------------------->|\0 |
8
   +------+                       +---+      +---+
9
   |   o------------------------------------>|\0 |
10
   +------+                       +---+      +---+
11
   |   o------------------------->|\0 |
12
   +------+                       +---+
13
   |   o-----------+
14
   +------+        |     +---+---+---+---+---+---+---+---+---+
15
   |   o  |        +---->| E | I | N | S | T | E | L | L |\0 |
16
   +---|--+              +---+---+---+---+---+---+---+---+---+
17
       |
18
       |       +---+---+---+---+---+---+---+---+
19
       +------>| Z | U | R | U | E | C | K |\0 |
20
               +---+---+---+---+---+---+---+---+

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.

von Marcel (Gast)


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

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.