Forum: Compiler & IDEs malloc und Strukturen gehen nicht


von Sven H. (sven91)


Lesenswert?

Hallo,

ich habe mich entschlossen mit den Mikrocontrollern auf C umzusteigen 
und mache gerade ein Buch durch.
Ich habe keinen reinen C-Compiler sondern einen C++-Compiler
(Visual Studio). Bis jetzt hat ALLES funktioniert bis auf malloc.
Das erste Problem stand sogar im Buch als Hinweis, dass man bei C++ vor 
malloc (char*)malloc braucht.
Aber jetzt bei den Strukturen geht gar nichts mehr.
Im Internet habe ich nicht wirklich was gefunden...

Frage: Wie muss der Quelltext aussehen, dass er funktioniert bzw. was 
ist der Fehler?

Erst das Programm und darunter ein paar Fehlermeldungen:
1
#include<stdio.h>            
2
#include<string.h>
3
#include<malloc.h>
4
#include<stdlib.h>
5
6
int main()
7
{
8
  struct Daten
9
  {
10
    int Personnummer;
11
    char Vorname[30];
12
    char Nachname[30];
13
  };
14
15
  struct Daten* Pointer = NULL;
16
  puts("Datenbank:");
17
18
  Pointer=(char*)malloc(sizeof(struct Daten));
19
  if(Pointer == NULL)
20
  {
21
    puts("Arbeitsspeicher ist voll!");
22
23
    fflush(stdin);
24
    getchar();
25
    exit(0);
26
  } 
27
 
28
  Daten->Personennummer = 1;
29
  strcpy(Daten->Vorname,"Mark");
30
  strcpy(Daten->Nachname,"Mustermann");
31
  printf("Person Nummer: %i\n", Daten->Personennummer);
32
  printf("Vorname: %i\n", Daten->Vorname);
33
  printf("Nachname: %i\n", Daten->Nachname);
34
35
  free(Pointer);
36
  Pointer = NULL;
37
38
  fflush(stdin);
39
  getchar();
40
  return 0;
41
}
error C2440: '=': 'char *' kann nicht in 'main::Daten *' konvertiert 
werden
error C2143: Syntaxfehler: Es fehlt ';' vor '->'
error C2819: Der Typ 'main::Daten' hat keinen überladenen 
Elementoperator '->'
error C2232: '->main::Daten::Vorname': Der linke Operand ist vom Typ 
'struct', verwenden Sie '.'

13 Fehler 0 Warnungen

mit freundlichen Grüßen

Sven

von 42 (Gast)


Lesenswert?

> Daten->Personennummer = 1;
> [...]

Müsste das nicht überall Pointer->... heissen?

von Peter II (Gast)


Lesenswert?

> Das erste Problem stand sogar im Buch als Hinweis, dass man bei C++ vor
> malloc (char*)malloc braucht.
du solltest erstmal rausbekommen warum das so gemacht wird. Wenn du das 
rausbekommen hast dann müsste dir klar sein wie man es bei der struct 
macht.

Du kannst auch die datei statt mit .cpp auch .c nennen, dann wird sie 
als c compiliert.

von Peter II (Gast)


Lesenswert?

Nachtrag:

Für welche µC sollte diese übung denn werden? Wenn es für die kleinen 
AVR Tiny und Mega werden soll. Dann sollte man malloc komplett 
weglassen.

von Sven H. (sven91)


Lesenswert?

Hallo,

vielen Dank für eure schnellen Antworten.
Ich glaub ich hab heut schon ein bisschen zuviel Programmiert.
Diese zwei Anfängerfehler habe ich ausgebessert:
Daten durch Pointer getauscht (Danke 42)
Personennummer durch Personnummer getausch (aua)

jetzt kommt nur noch ein Fehler:
(16) : error C2440: '=': 'char *' kann nicht in 'main::Daten *' 
konvertiert werden
Weiß da jemand weiter?

-> In der Zeile mit malloc

@Peter II:
wenn ich dich richtig verstanden hab:
Ich habe schon mehrere andere Übungen mit malloc gemacht - ist ein sehr 
Umfangreiches und sehr gutes Buch: C für Dummies xD (600 Seiten)
Wenn ich malloc in C++ richtig verstanden hab:
bei C++ muss der zurückgelieferte Speicher noch in den richtigen Wert 
umgewandelt werden.

zum Nachtrag:
Ich will damit Atmegas und Attinys(25,45,2313) flashen.
Warum soll man das dort weglassen?

mfg

Sven

von Peter II (Gast)


Lesenswert?

Sven H. schrieb:
> Wenn ich malloc in C++ richtig verstanden hab:
> bei C++ muss der zurückgelieferte Speicher noch in den richtigen Wert
> umgewandelt werden.
ja, und ist denn char* der richtige wert für deine struct?

> zum Nachtrag:
> Ich will damit Atmegas und Attinys(25,45,2313) flashen.
> Warum soll man das dort weglassen?
weil eine dynamische speicherverwaltung zu ineffizient ist, zu langsam 
und fehler sich damit noch schwerer finden lassen.

von Sven H. (sven91)


Lesenswert?

Peter II schrieb:
> ja, und ist denn char* der richtige wert für deine struct?

OK nein ist er nicht :)
Das hier hat funktioniert:
Pointer=(struct Daten*)malloc(sizeof(struct Daten));


Peter II schrieb:
> weil eine dynamische speicherverwaltung zu ineffizient ist, zu langsam
> und fehler sich damit noch schwerer finden lassen.

OK dann werde ich mir das merken - ich mache grad parallel auch noch ein 
Buch über Mikrocontroller durch.

Ich programmiere zwar schon länger Mikrocontroller in Bascom aber ich 
wollte tiefer einsteigen.


Vielen Dank jetzt funktioniert alles :)

mfg

Sven

von Patrick (Gast)


Lesenswert?

Peter II schrieb:
> weil eine dynamische speicherverwaltung zu ineffizient ist, zu langsam

Naja, das würde ich so nicht unbedingt unterschreiben.

Das Hauptproblem ist eher die Fragmentierung Deines (sehr begrenzten) 
Arbeitsspeichers durch dynamische Speicherallokationen.

Daher würde ich dringend empfehlen: Wenn schon dynamisch zur Laufzeit 
allokieren, dann bitte nur einmal zum Programmstart alles Benötigte auf 
einmal, und dieses dann nicht wieder wild freigeben, nachallokieren usw.

von Peter II (Gast)


Lesenswert?

Patrick schrieb:
> Daher würde ich dringend empfehlen: Wenn schon dynamisch zur Laufzeit
> allokieren, dann bitte nur einmal zum Programmstart alles Benötigte auf
> einmal, und dieses dann nicht wieder wild freigeben, nachallokieren usw.

dann kann man es ja auch gleich global machen.

und wenn man für ein 10byte dynmaische alloktion noch noch mal 2-3byte 
verwaltungsinformationen braucht, finde ich das ineffizient.

von DirkB (Gast)


Lesenswert?

Und beachte auch nochmal
Peter II schrieb:
> Du kannst auch die datei statt mit .cpp auch .c nennen, dann wird sie
> als c compiliert.

Im Visual Studio kannst du in den Project-Optionen auch angeben, dass du 
den C-Compiler verwenden willst.

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


Lesenswert?

Patrick schrieb:
> Das Hauptproblem ist eher die Fragmentierung Deines (sehr begrenzten)
> Arbeitsspeichers durch dynamische Speicherallokationen.

Das löst sich statistisch, man muss nur Reserven im Speicher übrig
lassen.  Funktioniert natürlich nur, wenn man ein wirklich dynamisches
Problem hat, d. h. die Datenanforderungen entstehen erst im Betrieb,
und die Daten selbst (bzw. deren Länge) ist statistisch verteilt.  In
einem solchen Fall wird man mit einer dynamischen Verwaltung allemal
besser fahren als mit dem Schema "statisch alles mit maximaler Größe
vorher allokieren", denn damit bekommt man insgesamt weniger Nutzdaten
unter.

Bei einem dynamischen Problem entsteht aber immer das Risiko, dass
man bei einer ungünstigen Konstellation der Eingabedaten out of memory
läuft; damit muss die Applikation irgendwie klar kommen.

Ist ein bisschen wie Ethernet: im Gegensatz zum Token Ring bietet es
zwar keinerlei Garantien, aber in der Praxis kann man deutlich sehen,
welche der beiden Varianten sich durchgesetzt hat.  Die Stochastik
funktioniert bis kurz vor der "Erbrechensgrenze", und nur der schmale
Bereich, in dem das Netz permanent an der Sättigung läuft wäre der,
wo Token Ring besser ist.

von Rolf M. (rmagnus)


Lesenswert?

Sven H. schrieb:
> zum Nachtrag:
> Ich will damit Atmegas und Attinys(25,45,2313) flashen.
> Warum soll man das dort weglassen?

Wie schon geschrieben wurde, ist der Speicher sehr begrenzt. Da muß man 
gegenüber dem PC, bei dem ein paar Bytes oder selbst ein paar Megabytes 
keine Rolle spielen, radikal umdenken. Der Tiny2313 hat z.B. 128 Bytes 
RAM, und da muß der Stack, alle statischen Variablen und noch der 
dynamische Speicher mit zusätzlichen Verwaltungsinformationen 
reinpassen. Da zählt recht schnell jedes einzelne Byte. Eine Instanz 
deiner Struktur braucht  z.B. bereits knapp die Hälfte(!) des 
verfügbaren Speichers, und das noch ohne den Overhead für den 
dynamischen Speicher.

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.