Zum Glück wurde der LUNA-Thread geschlossen. Ein Argument von c-hater beschäftigt mich aber doch: Es ist wohl für eine Programmiersprache wichtig, dass diese über Krücken wie Funktionspointer verfügt. Diese gibt es z.B. auch in Pascal als funktionale Parameter. Nur wozu braucht man die? Akademische Argumente kenne ich, in der Praxis habe ich sie noch nie gebraucht. Mache ich was falsch ;-)? Habt ihr Beispiele außerhalb des theoretischen Bereiches?
- Um einem Interrupt eine Funktion zuzuweisen - Callback Funktionen - ...
Bei diesem Projekt habe ich zB nen Funktionspionter genutzt umd ne Zeichensatz austauschen zu können: http://www.fritzler-avr.de/HP/ledscreen.php Da sind momentan nur Großbuchstaben drinne und wenn noch Kleinbuchstaben dazukommen sollen muss ja die Umwandlungsfunktion getauscht werden. Dabei handelt es sich um die get_seg16 in der seg16.c. Da könnte dann zB im Betrieb der Zeichensatz gewechselt werden. Ansonsten zB Interrupts, wenn man diese per Hand in die Interruptabelle einträgt. In die Tabelle muss ja nen Pointer auf den Interrupthandler der eine Funktion ist.
Jumptables zum Beispiel, wenn man eine Liste aus 20 Funktionen hat zum Durchführen 20 verschiedener Aktionen, und man einen Integer hat der angibt welche Aktion durchgeführt werden soll, kann man die Funktionspointer in ein Array packen und mit dem Index die richtige finden & aufrufen. Außerdem für callbacks, zB. um die Vergleichsoperation für qsort anzugeben. Oder z.B. bei der GUI-Programmierung gibt man der GUI-Library einen Funktionspointer damit sie eine Funktion im User-Code aufruft wenn der Benutzer einen Knopf gedrückt hat. Google "Pascal funktionale Parameter" liefert diesen Thread, was genau meinst du damit...?
Uihh, das ging ja fix. Danke für die Antworten. Aber wir sind im Forum Mikrocontroller, nicht PC- oder Betriebssystementwicklung. Braucht man sowas in diesem Bereich wirklich?
Guido B. schrieb: > Aber wir sind im Forum Mikrocontroller, nicht PC- > oder Betriebssystementwicklung. Braucht man sowas in > diesem Bereich wirklich? Es stehen doch genug Beispiele oben, die auch auf µCs zutreffen. Noch nie ein Menusystem in µCs gesehen? Oder einen simplen Timer-Scheduler?
Martin Wende schrieb: > Als ob auf so manchen ARM kein OS laufen würde und Interrupts hat man ja > nun wirklich fast überall? Ja, gut, aber von Linux sehe ich mal ab. A. K. schrieb: > Es stehen doch genug Beispiele oben, die auch auf µCs zutreffen. Noch > nie ein Menusystem in µCs gesehen? Oder einen simplen Timer-Scheduler? Auch schon selbst entwickelt, aber keine Funktionspointer hierfür benötigt. Peter Dannegger schrieb: > Beitrag "Wartezeiten effektiv (Scheduler)" Meine Programme warten nie, die gehen höchstens in den Sleep-Modus. Ich bin noch nicht überzeugt. ;-)
Virtuelle Funktionen und abstrakte Interfaces verwenden intern Funktionspointer, und sind ein sehr beliebtes und mächtiges Werkzeug zur Abstrahierung und Trennung von Interface und Implementation, und damit Trennung von einzelnen Komponenten komplexer Systeme. Beispiel: Verschiedene IO-Interfaces liefern Daten an, und verschiedene Programmkomponenten können diese entgegennehmen und unterschiedliche Aktionen vornehmen. Man kann für diese Komponenten (inkl. der IO-Treiber) nun abstrakte Interfaces definieren, sd. alle I/O-Interfaces von außen gleich aussehen ("es kommen bytes heraus") und man sie beliebig mit den weiterverarbeitenden Komponenten verbinden kann, und diese Bindung außerdem zur Laufzeit beliebig ändern kann. Die Entscheidung, welcher Code ausgeführt wird in Anhängigkeit davon was momentan womit verbunden ist, wird mit einem Funktionspointer getroffen (intern).
Guido B. schrieb: > Ich bin noch nicht überzeugt. ;-) Warum sollen wir dich überzeugen? Wenn man C kann, und effektiv nutzen will, kommt man früher oder später selber drauf, daß Funktionspointer ein äußerst mächtiges Werkzeug sein können.
Es geht hier ja wohl nicht darum was DU brauchst. Die Frag war "wozu". Und Fakt ist nunmal, dass Funktionspointer genutzt werden. Schwer ist es zudem auch nicht. Guido B. schrieb: > Ja, gut, aber von Linux sehe ich mal ab. Gibt ja nicht nur Linux.
Guido B. schrieb: > Ja, gut, aber von Linux sehe ich mal ab. Und die 1000 kleinen RTOS? Guido B. schrieb: > Auch schon selbst entwickelt, aber keine Funktionspointer hierfür > benötigt. Dadurch würde es aber modularer & wiederverwendbarer, da du den generischen Menücode komplett von dem Code trennen kannst, der die Liste der Menüpunkte und die durchzuführenden Aktionen definiert.
Guido B. schrieb: > Meine Programme warten nie, die gehen höchstens in den Sleep-Modus. Lies den Beitrag doch erstmal durch, es geht um das nicht blockierende Warten. Während Sleep kann die CPU ja nichts anderes machen.
Jede Klasse in C++ ist ein Funktionspointer, so werden die dereferenziert und damit sind wir beim Thema. Wenn Du in einem Programm dynamisch Funktionen ändern können willst nimmst Du einen "Voidpointer" und benutzt den um die dazugehörige Funktion aufzurufen, problematisch können dabei Parameter sein aber in C kann man ja beliebige Parameter übergeben, was natürlich eine weitere schöne Fehlerquelle ist. Und jetzt überlegen wir mal was der Funktionsname selber darstellt :-P
cppler schrieb: > Jede Klasse in C++ ist ein Funktionspointer, so werden die > dereferenziert und damit sind wir beim Thema. Wie kann denn eine Klasse ein Funktionspointer sein, auf welche Funktion zeigt der denn? cppler schrieb: > was natürlich eine weitere > schöne Fehlerquelle ist. ... die man zum Glück vermeiden kann!
@ Kindergärtner: Danke, jetzt wird es klarer. das macht also wirklich nur mit OOP Sinn. Aber Pascal kann es ja auch??? Fakt ist, dass es sehr trivial zu realisieren ist, das könnte jedem Compiler in ein paar Stunden beigebracht werden. Peter Dannegger schrieb: > Lies den Beitrag doch erstmal durch, es geht um das nicht blockierende > Warten. > Während Sleep kann die CPU ja nichts anderes machen. Sorry, Peter, ich habe nur die Anfangsbeschreibung gelesen, den Rest nehme ich mir morgen vor. Danke für die Erläuterungen.
Guido B. schrieb: > Danke, jetzt wird es klarer. das macht also wirklich nur mit OOP > Sinn. Gar nicht, siehe qsort! Aber in Kombination mit OOP wird es erst richtig interessant, ja. > Aber Pascal kann es ja auch??? Kann sein? > Fakt ist, dass es sehr > trivial zu realisieren ist, das könnte jedem Compiler in ein > paar Stunden beigebracht werden. Das kommt doch stark auf die Komplexität der Sprache und des Compilers an...
Praxis-Beispiel auf dem AVR ohne OOP: Zu jedem Sensor ein struct, in dem ADC-Kanal und ein Funktionspointer auf die Funktion mit der Spannung/Messwert-Kennlinie für den Sensor stecken, der µC hat nur gemessen, umgerechnet und ausgegeben. Die Alternative wäre eine switch-case-Orgie gewesen, mit Änderungen an zig verschiedenen Stellen, wenn sich die Sensorkonfiguration ändert. Die paar Byte verschwendeter RAM waren (wie fast immer) egal, dafür konnte man in ein paar Zeilen durch ein Array mit den erwähnten structs loopen und jeden Sensor gleich behandeln.
Guido B. schrieb: > Ich bin noch nicht überzeugt. ;-) Niemand zwingt dich dazu, sie zu verwenden. Du kannst Anwendungen auch für eine Turingmaschine schreiben, wenns dir behagt. ;-)
> Aber wir sind im Forum Mikrocontroller, nicht PC- > oder Betriebssystementwicklung. Ich springe damit z.B aus meinen Bootloadern in den Anwendungscode. Wie machst du das? Olaf
Guido B. schrieb: > Aber Pascal kann es ja auch??? Hinter jedem Sprung in eine Ereignisbehandlung verbirgt sich ein Funktionspointer.
Hi, Guido B. schrieb: > Martin Wende schrieb: ... > Ich bin noch nicht überzeugt. ;-) hier muss Dich ja auch keiner überzeugen. Prinzipiell kannst Du auch alles mit If-Then-Else oder Switch-Case Ketten machen, aber eleganter geht es halt oft mit Funktionspointern. Entscheide selbst ob Du die Hinweise annehmen möchtest. Das Beispiel mit den Menüs finde ich da ziemlich gut. Eine universelle Bibliothek für LCD-Menüs ohne Funktionspointer wird recht umständlich zu programmieren.
Bei vielen PIC Prozessoren kann man nicht direkt den Programmspeicher adressieren (Harvard Architektur). Wenn man Konstanten im Programmspeicher ablegen und nutzen möchte kann man zur Laufzeit des Programms auch nur über Call-Aufrufe da heran kommen. Das sind dann Funktionspointer, z.B direkt in Assembler ... Wie ist das bei den AVRs, die nutzen ja auch die Harward Architektur? Da gibt es ja die Makros in pgmspace.h . Lesen die Makros die Werte der Konstanten auch über Calls? Dann sind das auch Funktionspointer, auch wenn man es nicht sofort sehen kann. Jede Programmiersprache die man auf diesen Prozessoren den Programmspeicher für Daten nutzt muss dann ja, wenn auch versteckt, Funktionspointer nutzen können. Das Ganze macht natürlich nur für Arrays Sinn. Einfache Konstanten werden vom Compiler direkt als Werte in den finalen Maschinencode übersetzt.
Wolfgang Heinemann schrieb: > Lesen die Makros die Werte der Konstanten auch über Calls? Nein, das ist eine Besonderheit einiger PICs und liegt am fehlenden Ladebefehl, was wiederum mit der Befehlsbreite von 12/14 Bits zu tun hat. AVR hat den Befehl, PIC18 ebenso.
Wolfgang Heinemann schrieb: > Guido B. schrieb: >> Martin Wende schrieb: > ... >> Ich bin noch nicht überzeugt. ;-) Bitte richtig zitieren, ich hab nix gegen Funktionspointer...
Wolfgang Heinemann schrieb: > Bei vielen PIC Prozessoren kann man nicht direkt den Programmspeicher > adressieren (Harvard Architektur). Das ergibt sich nicht zwingend aus der Harvard-Architektur. Natürlich kann es einen Prozessorbefehl dafür geben; dass der dann u.U. 12 bit oder 8 + 4 liefert ist eine Detailfrage. Aber in der Frühzeit der PICs hat halt jemand entschieden, dass man den Befehl nicht braucht oder dass er zuviel kostet. Das ist aber nicht die einzige Merkwürdigkeit, manches an den PICs ist nur historisch zu verstehen. Auf Befehlsebene ist ein Funktionspointer eigentlich nur ein indirekter Sprung oder Call - springe zu der Adresse im Register Rx. Die Realisation in einer Hochsprache hat aber den grossen Vorteil der Typprüfung der Aufrufparameter, was man in Assembler selbst sicherstellen muss. Gruss Reinhard
Wozu braucht man Multiplikation? In der Praxis bin ich bisher immer mit Addition und Schleife ausgekommen. ;-)
Ich vergleich mal Funktionspointer mit einem Interfacen aus der OO (mit genau einer Methode) Dadurch lässt sich z.B. eine Sort Parameterisieren. ein mal solls aufsteigend sein, beim nächsten mal absteigend, beim nächsten mal nach laufzeit, einmal Strings, dann sinds Ints, dann negative Zahlen, ... Das ganze kann man über in der Funktion realisieren die man dem Sort beim Aufruf übergibt. Das ganze ist folgende Vorteile: - Der Sort ist generisch und kann damit wiederverwendet werden. Nur die Vergleichsfunktion ist neu anzupassen. - Es spart Code da der Sort Code nur einmal je Programm existiert. Nur die Vergleichsfunktionen kommt für jeden unterschiedlichen Sort das dein Programm benötigt neu dazu. - Testbarkeit, wenn dein Sort an sich mal funktioniert, und im neuen Programm nicht, dann liegt es mit sehr grosser warscheinlichkeit an der Vergleichsfunktion und nicht am Sort selber. - Testbarkeit, Fehlerbereinigungen im Sort wirken sich auf jede in deinem Programm verwendeten Sort aus. du musst den Fix nicht an 10 stellen nachziehen und ggf auch noch anpassen.
Funktionspointer braucht man für Sprungtabellen. Compiler setzen Switch/Case (Zustandsautomaten!) auch gerne mit sowas um. Und wenn der Compiler das intern können muss (und sei es für die Optimierung), warum nicht auch gleich dem Programmierer anbieten?
Svenska schrieb: > Funktionspointer braucht man für Sprungtabellen. Dafür sind indirekte Sprünge in der Maschine nützlich, aber keine Funktionspointer in der Programmiersprache. In der Programmiersprache wird das implementiert, was nützlich ist und halbwegs ins Konzept der Sprache passt. Nicht alles, was zufällig irgendwie geht.
Wem Funktionszeiger zu rustikal sind, der kann sich ja mal mit Closures befassen. Die sind z.B. in C nicht zu finden, aber deutlich universeller: https://en.wikipedia.org/wiki/Closure_(computer_science)
A. K. schrieb: > Wem Funktionszeiger zu rustikal sind, der kann sich ja mal mit Closures > befassen. Die sind z.B. in C nicht zu finden Dafür in den gängigen dynamisch typisierten Skriptsprachen und anderen. Closures sind ein klasse Mittel wenn man weiß wie man sie sinnvoll nutzt.
Guido B. schrieb: > Nur wozu braucht man die? Akademische Argumente kenne ich, in der > Praxis habe ich sie noch nie gebraucht. Mache ich was falsch ;-)? > Habt ihr Beispiele außerhalb des theoretischen Bereiches? Nö, wenn du sowas bislang nicht gebraucht hast, dann hast du damit nix falsch gemacht. Es gibt aber ne Menge Anwendungen dafür. Ein Beispiel kannst du in der Lernbetty (Codesammlung) im dortigen Menüsystem nachlesen. Dort hab ich nämlich das Menüsystem so organisiert. Jedes Menu-Item hat 1..3 solche Pointer, z.B. "OnDraw()" - das ist sozusagen die zu Fuß aufgesetzte und fertig im ROM gelinkte Objektorientiertheit, die man ja ansonsten in C nicht hat. Ich bezweifle auch, daß sich sowas in C++ machen läßt: Objekte nebst Hierarchie ohne Heap im ROM. Ansonsten kann man mit sowas auch ne nichtblockende prozedurale Funktionsweise (Statemaschine) in Systemen aufsetzen, die ansonsten rein ereignisgesteuert sind, ohne_ RTOS und _ohne jedesmal aus irgendeinem Status eine switch (..) Kaskade loszutreten. W.S.
Der Effizienz wegen. Wie würdest du zum Beispiel ein Menu implementieren?
1 | flash struct menuelement{ |
2 | unsigned char zahlvor; |
3 | unsigned char zahlnach; |
4 | unsigned char zahllinks; |
5 | unsigned char zahlrechts; |
6 | void (*tastehoch) (void); |
7 | void (*tasterunter) (void); |
8 | void (*tastelinks) (void); |
9 | void (*tasterechts) (void); |
10 | void (*menuPunktAnzeige)(void); |
11 | char flash *anzeigeString; |
12 | }
|
13 | menu[]={ |
14 | /*00*/{ 1, 1, 0, 0,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"-----Menu-----"}, |
15 | /*01*/{ 0, 0, 0, 2,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"Kalibrieren"}, |
16 | |
17 | /*02*/{ 6, 3, 0, 7,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"BremsPoti"}, |
18 | /*03*/{ 2, 4, 0,11,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"GasPoti"}, |
19 | /*04*/{ 3, 5, 0,16,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"Batterie"}, |
20 | /*05*/{ 4, 6, 0,19,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"Motor"}, |
21 | /*06*/{ 5, 2, 0, 1,menuHoch,menuRunter,nop,menuRechts,menuPunkt,"Zurück"} |
22 | };
|
23 | interrupt [EXT_INT2] void ext_int2_isr(void){ |
24 | if(tastenfrei){ |
25 | switch(PINB){ |
26 | case 0b11111010: menu[menuaktuell].tasterunter();break; |
27 | case 0b11111001: menu[menuaktuell].tasterechts();break; |
28 | case 0b11110011: menu[menuaktuell].tastehoch(); break; |
29 | case 0b11101011: menu[menuaktuell].tastelinks(); break; |
30 | default: tasteFalsch();break; |
31 | }
|
32 | tastenfrei=0; |
33 | }
|
34 | }
|
35 | ...
|
36 | |
37 | menu[menuaktuell].menuPunktAnzeige(); |
Hallo, hat mal einer in die libc geschaut wie dort stdio implementiert ist ? Speziell put und get im Filedescriptor sind Funktionspointer. Gruß, Michael
Michael Appelt schrieb: > Speziell put und get im Filedescriptor sind Funktionspointer. War(ist?) nicht immer so.
test schrieb: > case 0b11111001: menu[menuaktuell].tasterechts();break; hihihi... Dein Anliegen versteh ich schon, dennoch bist du damit zu kurz gesprungen. hint: und wer kümmert sich um 'menuaktuell'? W.S.
O.k. danke, ich glaube jetzt habe ich es kapiert. Der Vorteil resultiert aus der Kombination mit Tabellen über diese Pointer, deren Indizes sich z.B. aus dem Zustand einer FSM oder auch der Sensornummer ergeben, so dass nicht weiter unterschieden werden muss. Korrekt? Da muss ich mir mal Gedanken drüber machen.
Guido B. schrieb: > O.k. danke, ich glaube jetzt habe ich es kapiert. Der Vorteil > resultiert aus der Kombination mit Tabellen über diese Pointer, Das ist eine (sicher nicht unwichtige) Anwendung von Funktionspointern. Es wurden im Thread auch andere genannt, z.B. die austauschbare Compare-Funktion für immer denselben Sortieralgorithmus. In dieser Art gibt es noch viele andere Anwendungen. Du kannst jede beliebige Algorithmensammlung aus jedem Bereich der Informatik durchgehen, fast immer findest du darin auch welche, für die es sinnvoll ist, "tief innen" liegende Teilfunktionen ersetzbar zu gestalten, um eben diesen Algorithmus zur Laufzeit leicht auf unterschiedliche Anwendungfälle anpassen zu können. Parallel läuft z.B. gerade ein Thread von irgendsoeinem Loser, der Probleme damit hat, eine Bresenham-Linie mit variabler Strichstärke zu ziehen. Hätte die Pappnase innen im Bresenham einen Funktionspointer zum Aufruf einer PrintPen(x,y) vorgesehen, wäre der Drops sofort gelutscht. Eben diese Funktion müßte nämlich dann nur ausgetauscht werden... > Da muss ich mir mal Gedanken drüber machen. Nachdenken hat noch niemandem geschadet. Soviel ist mal sicher.
A. K. schrieb: > Die sind z.B. in C nicht zu finden, Aber dafür in C++11 :-)
1 | #include <iostream> |
2 | |
3 | template <typename F> |
4 | void range(int count, F f) { |
5 | for (int i = 0; i < count; i++) |
6 | f(i); |
7 | }
|
8 | |
9 | int main () { |
10 | int x = 0; |
11 | range(27, [&](int i) { |
12 | x += i; |
13 | });
|
14 | std::cout << x; |
15 | }
|
Ganz einfaches Beispiel, war gerade zu faul das für einen Sortieralgorithmus zu machen :) W.S. schrieb: > Ich bezweifle auch, daß sich sowas in C++ machen läßt: > Objekte nebst Hierarchie ohne Heap im ROM. Selbstverständlich geht das, einfach die Instanz als "const" angeben. Du kannst sogar die Initialisierungs-werte zur Compilezeit berechnen lassen in einer Art eingebauten funktional-Version von C++, durch die Verwendung von constexpr. C kann das nicht...
c-hater schrieb: > Parallel läuft z.B. gerade ein Thread von irgendsoeinem Loser (...) > Hätte die Pappnase (...) > Nachdenken hat noch niemandem geschadet. Soviel ist mal sicher. Dann fang Du mal an über Umgangsformen nachzudenken. Mit diesem Deinem Beitrag jedenfalls bist Du in Sachen Umgangsformen definitiv ein Loser.
W.S. schrieb: > Ich bezweifle auch, daß sich sowas in C++ machen läßt: > Objekte nebst Hierarchie ohne Heap im ROM. Hier noch ein kleines Beispiel dazu: http://ideone.com/IsG0UD Es wird eine Tabelle aus integern und deren Fakultätszahlen im ROM abgelegt. Diese besteht aus einer FacTable die die einzelnen Zahl-Fakultät -Kombinationen in Form von FacTable-Entry -Instanzen enthält. Die Fakultätszahlen werden automatisch vom Compiler berechnet und das Ergebnis landet als ein Block im ROM. In der main() folgt eine Test-Ausgabe. Meines Wissens geht so etwas in C nicht ohne externe Code-Generatoren (hässlich, fehleranfällig, unflexibel). Fakultätszahlen sind jetzt ein bisschen akademisch aber das ganze lässt sich auch wunderbar für echte Anwendungen einsetzen.
Rufus Τ. Firefly schrieb: > c-hater schrieb: >> Parallel läuft z.B. gerade ein Thread von irgendsoeinem Loser (...) >> Hätte die Pappnase (...) > >> Nachdenken hat noch niemandem geschadet. Soviel ist mal sicher. > > > Dann fang Du mal an über Umgangsformen nachzudenken. Mit diesem Deinem > Beitrag jedenfalls bist Du in Sachen Umgangsformen definitiv ein > Loser. Guck mal auf die Uhrzeit, wann er den Beitrag geschrieben hat. Je später der Abend, desto rüder der Ton. Kennt man doch schon. http://www.youtube.com/watch?v=mW08rCpM8lo mfg.
Kindergärtner schrieb: > Fakultätszahlen sind jetzt ein bisschen akademisch aber das ganze lässt > sich auch wunderbar für echte Anwendungen einsetzen. Ich bau mir nach ähnlichem Prinzip sin/cos-Tabellen, ist aber noch zu dreckig für die Öffentlichkeit. PS: Vorteil: Datentyp, Definitions- und Wertebereich lassen sich als Template-Parameter angeben. Compiler macht den Rest. Bis ca. 4096 Schritte pro 360 Grad geht das mit dem 16bit double beim AVR prima per Taylorreihe in constexpr.
Kindergärtner schrieb: > Selbstverständlich geht das, einfach... nanana, nimm mal den Mund nicht voller als du schlucken kannst. Ich schrieb von einem Menü-System im ROM. Ich hatte das damals für die Lernbetty außerhalb erzeugt - zuerst mit Script, dann per Pascal-Programm (sic!) Also, ich nehme dich mal beim Wort: Die Lernbetty ist in der Codesammlung ja immer noch zu finden, man kann dazu sowohl Keil als auch Yagarto benutzen und es wäre schon ein guter und frischer Wind darin, wenn du das Menü-System der Lernbetty mal übungshalber auf C++ umstellst - aber ohne den RAM zuzumüllen, denn der soll ja so gut es geht für die Apps freigehalten werden. Mach mal. (ist mein voller Ernst) W.S.
W.S. schrieb: > nanana, nimm mal den Mund nicht voller als du schlucken kannst. Sagt der, der solchen Code verbricht:
1 | #define RCST const struct TMenuItem // Globales 4-buchstabiges Makro...
|
2 | #define cl_white 0 // warum nicht einfach "const"
|
3 | #define cl_ltgr 1 // warum keine Klammern?
|
4 | #define cl_dkgr 2
|
5 | #define cl_black 3
|
6 | extern void Betty_Uhrzeit_OnEvent (RCST *self, word *aEvent); // unnötiges "extern", englisch & deutsch in EINEM Bezeichner... |
7 | |
8 | /* semantisch: diese konventionen sind die des WinAPI, auf ARM ist ein "word" 32bit,
|
9 | ein halfword 16bit und ein dword 64bit. Dein dword ist 4x so groß wie dein word.
|
10 | technisch: noch nie von typedef, von <stdint.h>, von <stdbool.h> gehört??? */
|
11 | #define word unsigned short int
|
12 | #define byte unsigned char
|
13 | #define dword unsigned long
|
14 | #define bool unsigned char
|
dazu mehrfache Definition derselben Datenstrukturen etc. Hoffentlich bezieht sich das *Lern*betty nicht auf "C lernen". Und ja, derartiges funktioniert auch in C++ komplett im ROM. Minimalbeispiel hier: http://ideone.com/Xfo20K Die MenuItem Klasse enthält über ihre vtable die Funktionspointer zu den Behandlungsmethoden, die abgeleiteten MyMenuItem1,2 implementieren dann konkrete Funktionen die auf die Ereignisse reagieren. Da es dem OOP-Prinzip ein wenig zuwiderläuft Interface und Daten zusammenzuspeichern, musste ich ein bisschen Pointermagic betreiben, funktioniert aber und ist dank static_assert auch sicher. Über die Konstante "myMainMenu" wird dann das ganze Menü zusammengebaut. Die Beispiel-main gibt einfach nur alle Menüeinträge am stdout aus und ruft 2 Eventhandler auf. Da "myMainMenu" als "constexpr const" markiert ist, ist der Compiler gezwungen das Menü komplett im ROM abzulegen. Bei diesem Programm landet außer den temporären Variablen in der main() nichts im RAM. Durch den Array-artigen Ansatz spart man sich pro Menüeintrag einen Pointer im Vergleich zu deinem linked list-Ansatz. Auf jedes MenuItem folgen seine Sub-MenuItems, deren Anzahl dem Eltern-MenuItem bekannt ist. So wird effizient eine rekursive Objektstruktur aufgebaut. Ich hätte noch etwas Wrappercode schreiben können um auch die Initialisierung rekursiv&elegant zu machen (s.d. man nicht selbst mit den subitem-Anzahlen rumhampeln muss), aber das würde es jetzt etwas unnötig verkomplizieren. W.S. schrieb: > wenn du das Menü-System der Lernbetty mal übungshalber auf C++ umstellst Klar, wenn du das sagst... Ich glaub ich habe bessere "Übungen". W.S. schrieb: > aber ohne den RAM zuzumüllen Wer hat eigentlich den Mythos in die Welt gesetzt, C++ würde irgendwas zumüllen? Das kann man eigentlich eher von C und der ganzen void-Pointerei sagen. W.S. schrieb: > Yagarto ... kommt nicht mit FPU's klar, der gcc-arm-embedded ist da besser.
Thorsten schrieb: > - Um einem Interrupt eine Funktion zuzuweisen > - Callback Funktionen > - ... Genau deswegen. Vor allem wenn man Sachen modular aufbauen will.
Kindergärtner schrieb: > Sagt der, der solchen Code verbricht:... Herzlich gelacht. ach, Junge, herumlabern kann jeder, es besser machen nur wenige. Du regst dich auf über "Denglisch"? oder über #define ? oder über einen griffigen RCST? oder über word, dword, bool und Konsorten? Die hat es schon gegeben, als ARM noch in den Kinderschuhen steckte. Da hast du noch was übersehen: ein GOTO in main. Furrrchtbar. Und seit wann ist "extern" derart überflüssig, daß man es nicht verwenden sollte? Wenn ich mir hingegen das anschaue: int main () { for (auto& item : myMainMenu) { std::cout << item.m_label << std::endl; } myMainMenu [0].onDraw (); myMainMenu [1].onKey (); } dann ist mir klar, daß du wahrscheinlich überhaupt nix verstanden hast und bloß wie Beckmesser in Nürnberg die Anzahl der Pointer zählst. Und zum Schluß, den Satz "Ich glaub ich habe bessere "Übungen"" halte ich für nen mißlungenen Versuch des Rückzugs. Du kannst es einfach nicht, möchtest dich aber dennoch großartig fühlen - das ist es. Kann ich verstehen, wer von uns möchte denn nicht insgeheim auch mal sich großartig fühlen... Also: entweder wirklich mal was Besseres für die Lernbetty vorlegen oder einfach sich in etwas mehr Bescheidenheit ergehen. So, Schluß für heute, den Rest Malbec (Argentinien, 2011) trinke ich jetzt aus und dann Nachtruhe. Wünsch ich ebenfalls allen Mitlesesern. W.S.
Kindergärtner schrieb: > Und ja, derartiges funktioniert auch in C++ komplett im ROM. > Minimalbeispiel hier: http://ideone.com/Xfo20K ziemlich interessant. Wenn ich demnächst mehr Zeit habe, muss ich das mal im Detail studieren und mich mit Templates mal etwas weiterbilden. :-) Meine schwache Stelle :-)
W.S. schrieb: > Herzlich gelacht. Dito. > ach, Junge, herumlabern kann jeder, es besser machen nur wenige. Ich habe dir ja gezeigt wie es besser geht. > Du regst dich auf über "Denglisch"? oder über #define ? oder über einen > griffigen RCST? oder über word, dword, bool und Konsorten? Die hat es > schon gegeben, als ARM noch in den Kinderschuhen steckte. Das kann sein, aber besser wirds dadurch nicht. Tatsächlich generiert solch altes Zeug auch heute noch eine Menge unnötiger Probleme. > Da hast du noch was übersehen: ein GOTO in main. Furrrchtbar. Ich hatte nur ganz kurz einige Stellen überflogen, ich bin mir sicher es gibt noch eine ganze Reihe lustiger vorbildlicher Dinge in deinem Code. > Und seit > wann ist "extern" derart überflüssig, daß man es nicht verwenden sollte? C99 oder sogar schon früher. Bei Variablen braucht man es, bei Funktionen ist es überflüsslig. > Wenn ich mir hingegen das anschaue: > int main () { > for (auto& item : myMainMenu) { > std::cout << item.m_label << std::endl; > } > myMainMenu [0].onDraw (); > myMainMenu [1].onKey (); > } > > dann ist mir klar, daß du wahrscheinlich überhaupt nix verstanden hast > und bloß wie Beckmesser in Nürnberg die Anzahl der Pointer zählst. Dann erleuchte mich, was für Probleme gibt es hier deinem Verständnis nach? Das std::out Zeug läuft natürlich nur am PC (oder wo man stdout hat), aber zur Demonstration ist das praktisch. Die Iteration ist das elegante, sichere & abstrakte C++ Äquivalent zur klassischen C-Pointer-Inkrement-Loop, und genau so effizient (im Endeffekt wird nur ein Pointer auf den Anfang des Arrays gesetzt und der solange hochgezählt bis man am Ende angekomemn ist). > Und zum Schluß, den Satz "Ich glaub ich habe bessere "Übungen"" halte > ich für nen mißlungenen Versuch des Rückzugs. Oder lediglich als Hinweis das ich nicht den ganzen Tag rumsitze und auf Vorschläge von dir warte. > Du kannst es einfach > nicht, möchtest dich aber dennoch großartig fühlen Ich kann - und mache! - noch viel bessere Sachen, und deswegen fühl ich mich auch ganz toll. > großartig fühlen... Also: entweder wirklich mal was Besseres für die > Lernbetty vorlegen oder einfach sich in etwas mehr Bescheidenheit > ergehen. Ist in Arbeit, dauert nur noch ein bisschen. Wird dann auch nicht unter diesem Nick veröffentlicht :-P Karl Heinz Buchegger schrieb: > Wenn ich demnächst mehr Zeit habe, muss ich das mal im Detail studieren > und mich mit Templates mal etwas weiterbilden. :-) Meine schwache Stelle Sehr gut :-) Templates (und constexpr) sind sehr mächtig und besonders für Mikrocontroller interessant, da man so viel Strukturierung&Rechnung zur Compilezeit durchführen kann. Bei ungeschickter Verwendung kann man eventuell mehr Code als beabsichtigt generieren, daher muss man wissen was man tut... :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.