Forum: Compiler & IDEs Dynamische Strukturen avr-konform


von Günther F. (taraquedo)


Lesenswert?

Hallo!

Ich sammle gerade meine ersten Erfahrungen mit dem avr-gcc. Vorher habe 
ich bereits unter Win und Linux mit C++ programmiert, so dass ich Gott 
sei dank nicht ganz im Regen stehe.

Jedenfalls brauche ich eine dynamische Speicherstruktur für einen 
struct, der eben beliebig viele male vorkommen kann. Dazu würde ich 
sowas wie den vector-Template in der stl nutzen, aber sowas gibt es hier 
ja (scheinbar) nicht. Muss ich jetzt das Rad neu erfinden und eine 
verkettete Liste mit all ihren Funktionen schreiben, die benötigt werden 
oder geht es auch irgendwie anders?

Grüße!

P.S.: Leider gibt es das malloc-Tutorial noch nicht. Wird sicher sehr 
interessant.

von Ulrich (Gast)


Lesenswert?

du solltest davor wissen wieviel du an speicher brauchst.
ERzähl mal was du machen willst und irgendjemand sagt dir dan wie dus 
machen könntest....

von ???????? (Gast)


Lesenswert?

@ Günther Frings:
AVR gcc unterstützt keine Objektorientierung !
Daher alles schön im alten C Linked-List-Stil machen.
Wobei "beliebig viel" bei ein paar k RAM eigentlich keinen Sinn macht ?
Wäre dann sowas:
1
typedef struct linkedlist {
2
    int datum;
3
    struct linkedlist *next;
4
  } llist;
5
6
  llist *head = NULL;
Und stl mit Containern kannste gleich vergessen :P
Und statt new mit malloc und free arbeiten :P

von Günther F. (taraquedo)


Lesenswert?

Hi!

Ja, das sind ganz neue Herausforderungen im Programmierstil. Habe auch 
rausgefunden, dass man statt überladener Funktionen auch einfach ein 
DEFINE nutzen kann, um z.B. sowas zu machen:

void fkt_xy(uint8_t x, uint8_t y);
#define fkt_x(x) fkt_xy(x, 0)

Das spart schonmal ein paar Bytes. Muss man echt clever sein. Meine 
LCD-Displayroutine belegt nämlich schon so etwa 564 Byte Flash.

Also ursprünglich wollte ich mit der dyn. Struktur auf meinem Display 
Bereiche definieren. Dann macht man einen Ausgabebefehl und er 
beschreibt nur diesen Bereich. Jetzt bin ich jedoch -platzschonender- 
dazu übergegangen einfach einen out_xy-Befehl zu erzeugen und dann mit 
define Konstanten zu definieren, die praktisch meine Bereiche 
darstellen. (z.B. out_xy("12%", EMPFANGSANZEIGE_X, EMPFNGSANZEIGE_Y); )

Mal davon ab. Habe gestern mal sowas versucht:
typedef struct { irgendwas... } mytype;
mytype* myvar;

myvar = malloc(sizeof(mytype));
myvar.irgendwas=...; // myvar jetzt nutzen
free(myvar);

Habe ich das so richtig verwendet? Denn mit dem Debugger kam ich noch 
nicht so recht zurecht. Der zeigte mir nach der Zuweisung zu 
myvar.irgendwas immernoch 0 an. (Ich habe eh den Eindruck, dass der 
Debugger manchmal etwas rumspinnt)

Grüße!

von Oliver (Gast)


Lesenswert?

Der Schritt von C nach C++ ist verdammt schwierig, aber zurück ist es 
leider genauso.

Vergiß alles, was du über Objekte, Verebung, Überladung, etc. kennst. 
Das gibt es nicht mehr. Ab jetzt geht es nur noch funktionsorientiert, 
und hardwarenah.
Und solche Verrenkungen wie

void fkt_xy(uint8_t x, uint8_t y);
#define fkt_x(x) fkt_xy(x, 0)

sparen NullKommaGarnix, sie führen nur zu völlig unlesbarem und damit zu 
mit Sicherheit nicht fehlerfreiem Code.

"Meine LCD-Displayroutine belegt nämlich schon so etwa 564 Byte Flash." 
Wow. Welchen AVR benutzt du denn? Wenn dich schon 564 byte Flash in 
Bedrängnis bringen, dann hat der so wenig RAM, daß du über C, C++, oder 
gar malloc() wirklich nicht nachzudenken brauchst.

Oliver

von Oliver (Gast)


Lesenswert?

Nachtrag:

Die Doku ist eigentlich eindeutig:
If malloc() fails, a NULL pointer is returned

Oliver

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


Lesenswert?

> AVR gcc unterstützt keine Objektorientierung !

So'n Quatsch.

Davon abgesehen, dass man objektorientiert auch in C programmieren
kann, ist C++ sehr wohl (mit Einschränkungen) unterstützt.

von Günther F. (taraquedo)


Lesenswert?

Hallo nochmals!

@Oliver:
Nein, das mit den 564 Bytes bringt mich nicht in Bedrängnis. Es ist ein 
ATMega8515 und das sind gerade mal 6%. Aber ich wollte noch höher hinaus 
und GPS auswerten, Modem ansteueren und sowas. Ich hoffe, das ich 
später nicht noch den Kontroller wechseln muss. Aber nicht das hier 
jetzt jemand sagt: 564 Bytes nur für ein Display- was hast Du da denn 
gemacht? Ich habe nämlich auch schonmal Asembler für avr geschrieben und 
meine nicht so große Texte geschrieben zu haben.

Jedenfalls malloc lieferte einen Wert zurück. Nur die Zuweisung war im 
Debugger nicht sichtbar, obwohl die Variable erschien - kann es sein, 
dass sie wegen fehlender Benutzung rausoptimiert wurde?

Und dann noch die Frage: Wenn define unübersichtlich wird, was kann ich 
statt dessen benutzen, um nicht immer einen Parameter mitübergeben zu 
müssen, der sich praktisch fast nie ändert?

Grüße!

von ????????????? (Gast)


Lesenswert?

@ Jörg Wunsch:
>So'n Quatsch.
>
>Davon abgesehen, dass man objektorientiert auch in C programmieren
>kann, ist C++ sehr wohl (mit Einschränkungen) unterstützt.

Guckste hier:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus
Was nützt Dir da 'nen .cc file, wenn die ganzen Vorteile von C++ nicht 
nutzbar sind ?
Vom Overhead wegen der notwendigen Runtimeverwaltung mal ganz abgesehen.

@ Günther Frings:
Für Displays gibt es guten Code in der Codesammlung und die 
Fleury-LCD-Lib ist auch OK ;)
Also ein Präprozessorstatement ist schon OK, nur wenn Du sowieso eine 
LCD Routine für die Ausgabe hast, dann reicht doch dort einmal die 
Funktion mit der Null hinten reinzuschreiben ?
Wäre dann z.B. sowas:
1
void updatedisplay(uint_8t spalte, char* inhalt)
2
{
3
 fkt_xy(spalte, 0);
4
 fkt_schreibwas(inhalt);
5
}
Oder hab' ich was verpaßt ?
Wegen Comilerschaltern einfach mal in der Doku nachsehen und im Fall des 
Falles kann auch alle Optimierung ausgeschaltet werden.

von A.K. (Gast)


Lesenswert?

"Was nützt Dir da 'nen .cc file, wenn die ganzen Vorteile von C++ nicht
nutzbar sind ?"

Weil noch einiges bleibt. Saubere Modularisierung, 
Vererbung/Abstrahierung einschliesslich virtual functions, Templates.

Beispiele für nützliche Templates:

- Generische Pufferklasse, verwendbar für I/O-Pufferung von UART Daten, 
CAN-Messages, ... Wie üblich kann man das auch in C, aber wenn man C++ 
schon kennt ist das deutlich eleganter.

- Konfigurierbare I/O-Module mit Konfigurationsparametern als 
Template-Argumente statt #defines. If/else-Konstruktionen sind meist 
erheblich lesbarer als zigfaches unübersichtliches #ifdef/#else.

- Puffergrösse als Template-Argument erlaubt statische 
Speicherallokation. Als Funktionsparameter eines I/O-Moduls hingegen 
benötigt das dynamische Allokation, bei der man weit weniger Übersicht 
über den belegten Speicher hat. Auch das geht anders, aber verletzt dann 
bisweilen Modularisierungsregeln.

Dynamische Speicherverwaltung sollte man sich allerdings bei Controllern 
abgewöhnen.

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.