www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Strukturmember zuweisung falscher Datentyp


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,


bin gerade dabei ein Menü zu erstellen. Jetzt bin ich auf ein Problem 
gestossen, das ich mir bisher nicht beantworten kann und hoffe das ihr 
mich auf den Pfad der Erleuchtung führen könnt :)




ich habe diese header Datei erstellt
#ifndef MEN_MENUE_H
#define MEN_MENUE_H


extern struct page_t hauptmenue;


/*   Struktur der Anzeige-Page. Jede Menüseite sowie Funktionsseite
*   wird durch diesen Struct definiert
*/
struct page_t{
  char bezeichnung[15];          // Menütext der Seite
  struct page_t *untermenuseiten_p[5];  // Array von Zeigern auf die Unterpages der aktuellen Page
  unsigned char selectedIndex;      // Aktuell ausgewählte unterpage 
  struct page_t *stammPage_p;        // Zeiger auf die Stamm/Elternpage
  void (*action)(unsigned char);      // Zeiger auf die Funktion die durch aktivieren ausgelöst wird
};


extern void MEN_initPages(void);



#endif // MEN_MENUE_H



Wollte nun in einer Funktion eine Page initialisieren. Wollte den Namen 
"Hauptmenue" einfach mal in "Test" ändern.

#include "MEN_Menue.h"

struct page_t hauptmenue = {"Hauptmenue",{0,0,0,0,0},0,0,0};

void MEN_initPages(void)
{

  hauptmenue.bezeichnung = "Test";


}



Wenn ich das aber mache, bekomme ich diese Fehlermeldung
(../Menue/MEN_main.c:8: error: incompatible types in assignment)
und er markiert mir die Zeile   ( hauptmenue.bezeichnung = "Test"; )



Ändere ich jetzt in meiner Struktur den member "bezeichnung", das 
anstatt
char bezeichnung[15];
char *bezeichnung;

geschrieben wird, bekomme ich beim kompilieren keinerlei Fehlermeldungen 
mehr.


Wo liegt hier der Fehler ? die Zeichenkette "Test" war doch weniger wie 
15 Zeichen lang.......



danke schonmal fürs lesen

gruss Maggus ;)

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir mal an, was Strings in C eigentlich sind.


Gruß
Lasse

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal damit:

strcpy(hauptmenue.bezeichnung,"Test");

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lasse S. schrieb:
> Guck dir mal an, was Strings in C eigentlich sind.

Ich weiss das Strings aus einem char Array mit '/0' am Ende bestehen. 
Und das "bezeichnung[0]" eigentlich ein Zeiger auf die Adresse der 
ersten Stelle dieses Arrays ist.
Wenn ich eine Zeichenkette zuweise, die länger ist wie char's reserviert 
wurden, überschreibe ich mir den Arbeitsspeicher. Die Gefahr laufe ich 
bei der zweiten Zuweisung von
 
char *bezeichnung = "test";
bezeichnung = "Das ist zu lang"
wenn mich nicht alles täuscht.



Das erklärt mir aber nicht, wieso ich beim initialiseren von
struct page_t hauptmenue = {"Hauptmenue",{0,0,0,0,0},0,0,0};
die Zwueisung machen darf, und später in der Funktion
hauptmenue.bezeichnung = "Test";
auf einmal nichtmehr.


Das würde ja bedeuten, das der Compiler bei einer einfachen Zuweisung 
und einer initialisierung unterschiede mit den Datentypen machen würde.


Will das jetzt nicht bis ins kleinste erklärt bekommen wenn es zu 
Umfangreich ist, aber ich würde mich über einen Schups in die Richtige 
Richtung freuen, damit ich weiss wo ich nachlesen muss (das wird 
wahrscheinlich nicht wenig sein :D )


gruss Maggus

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar,

danke dir Dirk.

Strings im Nachinein zu verändern geht ja in C garnicht so einfach wie 
ich mir das gerade vorgestellt hatte.

Ich glaube ich lasse die Initialisierung bei der Variablendeklaration 
einfach weg.

Eben hab ichs verstanden......... ;)

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder auch nicht :D


Wieso muss ich den String mit

strcpy(hauptmenue.bezeichnung,"Test");

in die Struktur kopieren?
Selbst wenn ich die initialiserung am Anfang weglasse und nur zuweise, 
schreibt er den selben Fehler heraus.


Ich hab irgendwo noch einen ziemlich dicken Denkfehler drin......

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich mir gedacht :-)

Der Knackpunkt ist, wann und wie der Compiler die tatsächliche Länge des 
Strings überhaupt feststellen kann.

Deswegen der Unterschied zwischen Initialiserung und Zuweisung.Die 
Initialisierung sieht nur oberflächlich so aus wie eine Zuweisung. Der 
Punkt ist nicht der Typ sondern, das der Compiler, da er bei der 
Initialisierung die Länge des Strings kennt auch den Speicher dafür 
reservieren kann. Eine Zuweisung aber findet nicht zur Compilierzeit 
sondern zur Laufzeit statt. Dann aber kann der Compiler nichts mehr 
machen. Er ist garnicht mehr aktiv. Und die Programme bekommen keinen 
Code mit um zur Laufzeit die Länge von String zu berechnen wenn eine 
Zuweisung auftritt.

Das Ergebnis von dem oben gesagten ist, das Du zur Laufzeit selbst 
Speicher reservieren musst (alloc, malloc) und den String selbst 
kopieren musst (strcpy).

Das der Compiler bei strcpy denselben Fehler bringt wie bei dem Versuch 
der Zuweisung halte ich, sagen wir mal, für einen Irrtum.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Selbst wenn ich die initialiserung am Anfang weglasse und nur zuweise,
>schreibt er den selben Fehler heraus.

Uups. Halt. Da habe ich falsch gelesen.

Der Knackpunkt ist wiegesagt, die Zuweisung. Zur Laufzeit kann das 
Programm nicht selbst die Länge berechnen und Speicher reservieren. Das 
musst Du dann selbst machen.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, ....

Lars hatte recht. Ich muss nochmal lesen wie ich Strings in C behandeln 
muss :D

das deklarieren von Strings über ein Array mit
 char text[15]; 
birgt doch mehr verständniss das man haben muss.


ich merke mir mal:
Wenn das char Array bereits angelegt wurde, sprich der Speicher 
bereitgestellt, muss dieser per Hand befüllt werden
text[0] = 'a'
text[1] = 'b'
etc.

Das ist deshalb nötig , da zur Laufzeit der Reservierte Speicher durch 
zuweisungen wie
text = "Test";
nichtmehr automatisch angepasst werden kann, wie es der Compiler machen 
würde.


Glaube das klingt ganz gut.....

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

Bewertung
0 lesenswert
nicht lesenswert
Markus schrieb:

> ich merke mir mal:
> Wenn das char Array bereits angelegt wurde, sprich der Speicher
> bereitgestellt, muss dieser per Hand befüllt werden
> text[0] = 'a'
> text[1] = 'b'
> etc.

Quatsch,
Das kann man so machen, wenn man Masochist ist.
Man kann aber auch ganz einfach die Sammlung der str.. Funktionen 
benutzen, die in deiner Laufzeitumgebung schon fertig vorhanden sind.

> Das ist deshalb nötig , da zur Laufzeit der Reservierte Speicher durch
> zuweisungen wie
> text = "Test";
> nichtmehr automatisch angepasst werden kann, wie es der Compiler machen
> würde.

Jain.
Der Knackpunkt ist, dass man in C keine Arrays zuweisen kann.
Arrays sind in C Bastarde, die sich nicht ganz so verhalten, wie andere 
Datentypen.

Spar dir das rumraten, kauf dir ein C Buch und arbeite das erste Drittel 
durch. Dann kennst du das alles und brauchst nicht mehr raten.

In der Zwischenzeit, bis du dein Buch hast, kannst du dich hier mal über 
Strings einlesen.
http://www.mikrocontroller.net/articles/FAQ#Wie_fu...

Autor: Blif (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mit
 struct page_t hauptmenue = {"Hauptmenue",{0,0,0,0,0},0,0,0}; 
sagst du dem Compiler, er solle dir die Strucktur 'hauptmenu', wie in 
den geschweiften Klammern beschrieben vor initialisieren. - Der Compiler
erledigt das.

Weiter unten in
 hauptmenue.bezeichnung = "Test"; 
weist du einen Zeiger einem Array zu. Der String "Test" ist als 
Konstante
im Code abgelegt und du hältst einen Zeiger darauf. Der C Compiler hat 
keine
Ahnung wie er den Zeiger dem Array zuweisen soll. Du musst also den Text 
mit
strcpy() hinein kopieren.

Hoffe es hilft weiter

Gruss

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf jedenfall habt ihr mir schonmal ein gutes Stück weitergeholfen was 
mein Verständnissproblem betrifft.Danke nochmal...


Habe mir

"Programieren in C" von Kernighan und Ritchie gekauft
( Sehr detailliert, aber was das Thema hier betrifft schwer zu erlesen)

und

"Softwareentwicklung in C für Microprozessoren und Microcontroller" von
J. Wiegelmann
( Cooles Buch, macht Spass zu lesen)

gekauft


Meiner Meinung nach sind solche Kniffe die den Compiler betreffen, aus 
diesen Büchern (falls überhaupt vorhanden) nur schwer auszulesen.

Gibt es denn gute Bücher über den GCC Compiler zu kaufen, die auf 
Anfänger wie mich hin zielen und mir bei solchen Problemen weiterhelfen 
können ?

Wenn ich das hier so lese, ist das ja ziemlich verständlich, aber der 
Vorteil von diesem Forum ist das ihr auf meine Fragen eingehen könnt. 
Das kann ein Buch nicht.


Bin ja echt froh das es das Forum hier gibt ;)

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Meiner Meinung nach sind solche Kniffe die den Compiler betreffen, aus
>diesen Büchern (falls überhaupt vorhanden) nur schwer auszulesen.

Das ist kein Kniff. Das ist die Sprachdefinition und die lernst Du aus 
Deinem Buch. Man Vektoren initialisieren aber nicht zuweisen. Punkt.

>Gibt es denn gute Bücher über den GCC Compiler zu kaufen, die auf
>Anfänger wie mich hin zielen und mir bei solchen Problemen weiterhelfen
>können ?

Das hat nichts mit GCC zu tun, sondern folgt aus der Sprachdefinition. 
Jeder Compiler macht das (hoffentlich) so.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tatsächlich ist meine Erklärung sozusagen eine nachträgliche.

Aber man kann das schliessen, wenn man mal selbst einen Compiler 
schreibt. Wenn Zuweisungen möglich wären müsste man Speicher 
alloziieren, evtl. den Zeiger verändern und sich Gedanken darüber 
machen, ob andere Zeigervariablen nicht evtl. auch diesen Zeiger 
enthalten. Wegen der Probleme die das mit sich bringt, ist man dankbar, 
das Zuweisungen nicht möglich sind.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube das Problem ist das ich gelernter Autoelektriker bin mit 
garkeine Ahnung von Informatik.

Ich versuche mir das ganze Autodidaktisch beizubringen, und da muss man 
eben einfach auf die Hilfe von Büchern zurückgreifen (od. Foren).

Deshalb entschuldigt die Fragen, ..... ;)

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.