Mark W. schrieb:> Ich bin gerade dabei fuer 30 ifs aus 150 Zeilen 30 zu machen.
was genau spart man, wenn man Zeilen spart?
Hast Du eine überempfindliche Return-Taste?
Mark,
falls du bei mir als Software-Entwickler arbeiten würdest, würde ich
dich allein für die Frage entlassen.
Du sparst keine Lesearbeit, du machst Arbeit. Warum denkt jeder
Programmmierer er wäre eine special Snowflake und besser als der
Compiler?
1. Schreib was du meinst
2. Verlass dich auf den Compiler
3. verwende in dem Projekt autoformat
4. das ganze soll geunit-tested werden
Mark W. schrieb:> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?> Oder geht das gar nicht?
möchte ich zeilen sparen, schreibe ich gar keinen code...
asdf schrieb:> Mark,>> falls du bei mir als Software-Entwickler arbeiten würdest, würde ich> dich allein für die Frage entlassen.>
Ooops. Naja, zum Glueck bin ich ja kein Software-Entwickler.
War auch nicht so ernst gemeint, wollte nur mal sehen was die Fachleute
dazu sagen.
Ging mir hier um die Uebersichtlichkeit, weil man da beim Schreiben
weniger scrollen muss.
Cool schrieb:> Ich wusste nichtmal dass man mit Switch Bereiche testen kann
Kann man auch regulär nicht, da dies nicht zum C-Standard gehört.
Bestimmte Compiler wie der gcc unterstützen dies als eine Erweiterung.
asdf schrieb:> Du sparst keine Lesearbeit, du machst Arbeit. Warum denkt jeder> Programmmierer er wäre eine special Snowflake und besser als der> Compiler?>> 1. Schreib was du meinst> 2. Verlass dich auf den Compiler> 3. verwende in dem Projekt autoformat> 4. das ganze soll geunit-tested werden
Fachlich eine sehr gute Antwort.
Aber das...
asdf schrieb:> falls du bei mir als Software-Entwickler arbeiten würdest, würde ich> dich allein für die Frage entlassen.
...ist ein ziemlich klingonischer Ansatz. Wenn Du über die Entlassung
von Mitarbeiter zu entscheiden hättest und tatsächlich so entscheiden
würdest (sprich: bei allen Fragen, Gedanken, Überlegungen der Kollegen,
die Du spontan dumm findest), wärst Du sehr schnell eine One-Man-Show.
Mark W. schrieb:> asdf schrieb:>> Mark,>>>> falls du bei mir als Software-Entwickler arbeiten würdest, würde ich>> dich allein für die Frage entlassen.>>> Ooops. Naja, zum Glueck bin ich ja kein Software-Entwickler.> War auch nicht so ernst gemeint, wollte nur mal sehen was die Fachleute> dazu sagen.> Ging mir hier um die Uebersichtlichkeit, weil man da beim Schreiben> weniger scrollen muss.
Also nur getrolle. Moderatoren: Thread und User können weg.
> Ich wusste nichtmal dass man mit Switch Bereiche testen kann
Wie schon geschurbt wurde ist das non-standard. Würde hierzufirma wohl
auch (berechtigterweise) zum Rauswurf führen.
Mark W. schrieb:> Hallo,>> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?> Oder geht das gar nicht?
Man kann alles machen - wenn man es sinnvoll begründen kann.
"Zeilen sparen" ist selten ein sinnvolles Argument. Für nicht
verwendeten Speicherplatz bei den Sourcecode-Dateien gibt es kein Geld
zurück. ;-)
Markus F. schrieb:> Mark W. schrieb:>> Ich bin gerade dabei fuer 30 ifs aus 150 Zeilen 30 zu machen.>> was genau spart man, wenn man Zeilen spart?>
Naja, ich finde es wird uebersichtlicher. Man hat mehr Code auf dem
Bildschirm und da es sich immer um die gleich Funktionalitaet handelt,
sieht man Fehler leichter, weil es eben symmetrischer ist.
Aber das ist ja relativ, verstehe schon, dass die Fachleute sich da an
geltende Standards halten sollten, speziell wenn man im Team arbeitet.
Bei mir schaut da keiner hin, ist nur privat.
Ok schrieb:> Also kurzer unleserlicher Code soll besser sein als Leserlicher bei dem> man länger scrollen muss...
Hmm, wenn ich mir das genau ueberlege, wer sagt denn dass es unleserlich
sein muss.
Wenn ich mein Beispiel nehme, dann wuerde ich das auch nach einem halben
Jahr noch verstehen.
Übersichtlich wird es, wenn man solche Monster-Abfragen in eine Funktion
wegräumt und die 150 Zeilen durch eine ersetzt:
1
calc_ou(output_mv,&o,&u);
Wenn in dieser Funktion, die nur eine Sache erledigt, 150 ähnliche
Zeilen stehen, stört das keinen. Die Testbarkeit wurde schon erwähnt.
Wenn man die Grenzen ständig anpasst, würde ich den Sourcecode dieser
Funktion generieren lassen, um Fehler zu vermeiden.
---------------------------------------
1
if(output_mV<100......
2
if(output_mV>99......
Die Grenzen so zu schreiben ist maximal verwirrend, weil für jede Grenze
zwei verschiedene Zahlen da stehen. Bei der nächsten Anpassung ändert
man die 100 und übersieht wahrscheinlich, dass die 99 auch hätte
geändert werden müssen. Hätte man
1
if(output_mV<100.........
2
if(output_mV>=100........
geschrieben, wäre das aufgefallen. Die verbreitete Aversion gegen <= und
>= erschließt sich mir nicht.
---------------------------------------
Mark B. schrieb:> "Zeilen sparen" ist selten ein sinnvolles Argument.
Wenn man eine Aversionen gegen die Benutzung von Funktionen hat, schon.
Wenn ich nur so ganz kurze Anweisungen habe, schreibe ich auch mal ein
if in eine Zeile, aber spätestens wenn ich mal den code beautifyer
starte, habe ich eh wieder mehrer Zeilen.
Außerdem gibts ja auch Code-Folding, falls man möglichst viel auf einmal
sehen muss.
Ivo
Die zweifach hingeschriebenen Grenzen kann man sich auch mit sinnvoll
plazierten elses sparen, wenn wie im Beispiel nur eine Zahl in
Wertebereiche eingeordnet werden soll:
Peter D. schrieb:> Rekursion mit variabler Argumentenliste, da kriegt man ja ne Knoten im> Gehirn.
Absolut gängige Praxis bei funktionaler Programmierung. So kann der
Aufrufer mit wenig Code eine konsistente Bereichs-Abfrage bauen. Auf
Wunsch fügt man noch eine Prüfung aufs Minimum hinzu.
Dr. Sommer schrieb:> Absolut gängige Praxis bei funktionaler Programmierung.
Wenn ich das richtig sehe, ist die Abbruchbedingung der Rekursion das
Fehlen weiterer Argumente.
Kann der Compiler sowas aufdröseln oder packt er wirklich zur Laufzeit
den gesamten Wust an Argumenten auf den Stack?
Peter D. schrieb:> Wenn ich das richtig sehe, ist die Abbruchbedingung der Rekursion das> Fehlen weiterer Argumente.
Richtig, aber die Bedingung wird beim Compilieren ausgewertet, nicht zur
Laufzeit. Die Aufruftiefe ist also fix.
Peter D. schrieb:> Kann der Compiler sowas aufdröseln oder packt er wirklich zur Laufzeit> den gesamten Wust an Argumenten auf den Stack?
Nur wenn nicht geinlined wird. Wenn man sichergehen möchte dass alles
geinlined wird schreibt man noch ein "__attribute__((always_inline))
inline" dran. Dann wird daraus praktisch eine simple if-else-Kette.
Was gefällt dir nicht an der Lösung, die schon weiter oben gepostet
wurde?
militanter Zeilensparer schrieb:> o = (output_mv / 100) * 2 + 4;> u =o + 1;
(ich hab sie mal leicht abgeändert, weil vorher imho eine Zahl nicht
exakt gestimmt hat)
Wenn deine 30 folgenden ifs alle so schön regelmäßig weiterzählen wie
die ersten drei, dann lässt sich das doch alles zu dieser einfachen
Formel zusammenfassen.
Achim S. schrieb:
> militanter Zeilensparer schrieb:>> o = (output_mv / 100) * 2 + 4;>> u =o + 1;
Habe ich gesehen. Habe nur noch nicht drauf geantwortet. Will ich morgen
mal ausprobieren.
Mark W. schrieb:> Naja, ich finde es wird uebersichtlicher.
Kann, muss nicht.
Damit es übersichtlicher wird, müsste es wirklich alles auch schön
formatiert werden, dass es am Ende wie eine Tabelle aussieht. In
solchen Fällen benutze ich sowas auch gelegentlich.
Der Gewinn an Lesbarkeit dadurch muss aber schon erheblich sein,
damit die Maßnahme gerechtfertigt ist.
ps: Das beißt sich dann natürlich mit der Überschrift, die du diesem
Thread gegeben hast. ;-) Wenn es dadurch wirklich "unleserlich"
wird, ist es niemals gerechtfertigt.
asdf schrieb:> 2. Verlass dich auf den Compiler
Dass man damit keinen Objektcode einspart, war wohl auch dem TE von
vornherein klar und in keiner Weise die Absicht.
Ivo Z. schrieb:> spätestens wenn ich mal den code beautifyer starte
Einem solchen kann man normalerweise auch sagen, dass er bestimmte
Bereiche, die sorgsam manuell formatiert worden sind, nicht anfassen
soll.
Mark W. schrieb:> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?> Oder geht das gar nicht?> if(output_mV < 100){o = 4; u = 5;}
Habe ich früher mal gemacht. Dann hat man aber ein Problem, wenn man den
Code schrittweise im Debugger durchgeht. Denn typischerweise springt der
Debugger beim Single-Stepping über die ganze Zeile drüber, egal ob die
Bedinung wahr oder falsch war. Um zu sehen, ob der Branch betreten
worden ist oder wäre, muss man sich also vorher und nachher die
Variablenwerte ansehen.
Schreibt man hingegen
1
if(output_mV<100){
2
o=4;
3
u=5;
4
}
dann sieht man beim Single-Stepping ganz klar, ob der Branch betreten
wird oder nicht.
Deshalb schreibe ich schon lange keine kompakten if-Einzeiler mehr.
Mark B. schrieb:> "Zeilen sparen" ist selten ein sinnvolles Argument. Für nicht> verwendeten Speicherplatz bei den Sourcecode-Dateien gibt es kein Geld> zurück. ;-)
"Zeilen sparen" kann aber ein sinnvolles Argument sein, wenn man dafür
eine Funktion komplett auf den Bildschirm bekommt, statt viel scrollen
zu müssen. Da muss man abwägen, was man nun besser lesbar findet: Alles
schön sauber in einzelne Zeilen geschrieben, dafür so, dass man ständig
scrollen muss, oder eher kompakt, dafür ist aber alles auf einen Blick
zu sehen. Für mich muss Variante 1 nicht zwingend und unumstößlich das
Optimum sein, auch wenn es hier Leute gibt, die das als Grund sehen
würden, jemanden auf die Straße zu setzen…
Ich würde es dann sauber untereinander schreiben, passend zu einander
eingerückt:
1
if(output_mV<100){o=4;u=5;}
2
if(output_mV>99&&output_mV<200){o=6;u=7;}
3
if(output_mV>199&&output_mV<300){o=8;u=9;}
4
if(output_mV>299&&output_mV<400){o=10;u=11;}
So finde ich das besser lesbar und schneller erfassbar, als wenn da jede
Klammer und jede Zuweisung ihre eigene Zeile bekommt. Und die
angegebenen 30 Zeilen passen komplett auf den Bildschirm, die 150 eher
nicht, was die Übersicht weiter verbessert.
Die vorher genannten Argumente, statt > 99 lieber >= 100 zu schreiben
oder gleich else zu nutzen, um sich jeweils die Untergrenze zu sparen,
sind auch sinnvoll.
Ivo Z. schrieb:> Außerdem gibts ja auch Code-Folding, falls man möglichst viel auf einmal> sehen muss.
Gerade das tut man bei Code-Folding ja nicht. Um zu erkennen, ob alle
Zuweisungen an o und u richtig sind, muss ich erst sämtliche Folds
öffnen.
tictactoe schrieb:> dann sieht man beim Single-Stepping ganz klar, ob der Branch betreten> wird oder nicht.
Bei üblicher brauchbarer Optimierung greift dieses Argument jedoch
so gut wie nicht. Wirklich zeilenweises Abarbeiten funktioniert nur,
wenn man nicht optimiert.
Rolf M. schrieb:> Ich würde es dann sauber untereinander schreiben, passend zu einander> eingerückt:> if ( output_mV < 100) { o = 4; u = 5; }> if (output_mV > 99 && output_mV < 200) { o = 6; u = 7; }> if (output_mV > 199 && output_mV < 300) { o = 8; u = 9; }> if (output_mV > 299 && output_mV < 400) { o = 10; u = 11; }
Ich auch, aber die Reihenfolge umdrehen und was weglassen:
1
if(output_mV<400){o=10;u=11;}
2
if(output_mV<300){o=8;u=9;}
3
if(output_mV<200){o=6;u=7;}
4
if(output_mV<100){o=4;u=5;}
Ob die bei kleinen Werten erfolgende wiederholte Zuweisung günstiger ist
als die Bereichsprüfung bei den größeren? Keine Ahnung, müsste man bei
zeitkritischen Bedingungen mal überlegen bzw. anschauen.
Solche "Zeilensparumstellungen" finde ich nur ok für die ersten paar
Zeilen (in TE Bsp: keinesfalls alle 30 ifs) und zwar als Schuhlöffel um
dem Gehirn bei der Mustererkennung auf die Sprünge zu helfen.
Letztlich muss solcher "tabellarisch datengesteuerter Code" nicht aus 30
ifs bestehen sondern aus einer Schlaufe und einer (inlined?) Funktion
welche sich durch die Wertetabelle arbeitet. Also wenn es sich nicht
direkt berechnen lässt wie militanter Zeilensparer es zeigt.
30 ifs erfordern streng genommen (mindestens!) n*30 Testcases welche
Niemand schreiben/pflegen/kontrollieren/protokollieren will. Für jede
neue Übersetzung durch den Compiler!
Die Schlaufe + Funktion ist hingegen mit 1..2 Handvoll Testcases
abgedeckt, ja sie kann sogar als binary wiederverwendet werden (lib zum
linken) und muss nie wieder nachgetestet werden auch wenn die
Parametertabelle andere Werte bekommt.
Dieser Gedankenablauf muss eigentlich schon stattfinden bevor 30 ifs
auf je mehreren Zeilen darniedercodiert werden... (ich hätte den Fleiß
dazu schon gar nicht, ich kann ja Programmieren und nicht nur nach
Diktat Code ergießen)
Achim S. schrieb:> militanter Zeilensparer schrieb:>> o = (output_mv / 100) * 2 + 4;>> u =o + 1;
Fantastisch.
Ich habe es jetzt so gemacht und es funktioniert. Es brauch nicht einmal
ein if Anweisung.
Gestern hatte ich ueberlegt und habe es nicht 100% verstanden wegen der
Rundung. Aber da o und u int sind und alles nach dem Komma wegfaellt
geht's wunderbar.
Auch alle anderen Vorschlaege haben meinen Horizont erweitert. :-)
militanter Zeilensparer schrieb:> if (output_mv >= 400) {> u = o = 0;> } else {> o = (output_mv / 100) * 2 + 2;> u =o + 1.;> }
Militanter Deleygenerator.
Auf nem µC dauern die div 100 deutlich länger als die paar if-Abfragen.
Karl schrieb:> Auf nem µC dauern die div 100 deutlich länger als die paar if-Abfragen.
Kennst du nur AVR? Schon Cortex m3 haben ein div in Hardware.
Die direkte Berechnung hat aber einen viel wichtigeres
Karl schrieb:> Oder man sucht ganz einfach in einer lut.
This.
Programmiersprachentheaterintendant schrieb:> Letztlich muss solcher "tabellarisch datengesteuerter Code" nicht aus 30> ifs bestehen sondern aus einer Schlaufe und einer (inlined?) Funktion> welche sich durch die Wertetabelle arbeitet.
And this. Nur deutlich besser ausgedrückt.
Aber gut, ich komme aus dem Automotive Bereich. Da würde man
gesteinigt für eine if Kaskade. Allein schon, weil man die daten zur
Laufzeit andern können muss.
Mark W. schrieb:> Hallo,>> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?> Oder geht das gar nicht?
Dein zu lösendes Problem besteht doch darin, in einer Menge von
rechts-offenen Intervallen das Intervall zu finden, das einen bestimmten
Wert beinhaltet. Und dieses Intervall möchtest Du durch einen Index
kennzeichnen.
Die Frage ist, warum willst Du bei Deiner Lösung Zeilen sparen?
Vermutlich, weil er unleserlich (geworden) ist.
Wann wird Code unleserlich? Wenn (zu) viel imperativ gemacht wird (wie
bei Dir).
Deswegen gibt es ja auch die Empfehlungen:
a) benutze Algorithmen / Funktionen, keine expl. Iterationen
b) benutze Algorithmen / Funktionen, keine expl. Alternativen
Diese Empfehlungen führen zu deklarativem Code, und der ist in den Augen
vieler besser lesbar, wartbar, testbar.
Code ist dann verständlich, wenn man explizit hinschreibt, WAS gemacht
werden soll, aber nicht das WIE.
Natürlich muss man irgendwo einen Algorithmus schreiben, der die o.g.
Intervalle konstruiert oder das Lookup durchführt. Dazu sind Iterationen
und Alternativen notwendig. Wenn man die in seinem Anwendungscode nicht
mehr haben will, gibt es nur die Möglichkeit, sie nach unten (oder
manchmal auch nach oben) in der Abstraktionsschicht zu schieben.
@Wilhelm M.
Ja das ist ganz nett, insbesondere da ich auch gerade mal wieder etwas
C++ lerne...
Aber wie ist denn der daraus erzeugte Assembler code? Wirklich gleich
gut optimiert als wie die ursprünglichen C Anweisungen? Bei uC ist das
ja schon relevant, und sonnst eigentlich auch.
Stefan schrieb:> @Wilhelm M.>> Ja das ist ganz nett, insbesondere da ich auch gerade mal wieder etwas> C++ lerne...>> Aber wie ist denn der daraus erzeugte Assembler code? Wirklich gleich> gut optimiert als wie die ursprünglichen C Anweisungen? Bei uC ist das> ja schon relevant, und sonnst eigentlich auch.
Habe es nicht ausprobiert, aber ich gehe davon aus, dass der mindestens
so gut wie die C Variante ist.
Das liegt daran, dass hier
1) die Intervalle constexpr sind, d.h. sie werden schon zur Compilezeit
berechnet, und
2) Funktionstemplates ja immer inline-Kandidaten sind, denn ihre
Definitions ist dem Compiler immer bekannt (template-header-only-libs
haben immer diesen Vorteil), so dass die Inline-Heuristiken immer
angewendet werden.
Markus F. schrieb:> warum nicht einfach per Lookup-Table?
Das macht der Code, den ich gepostet hatte ja.
> Dann kann man die Parameter auch noch zur Laufzeit ändern, falls> notwendig.>>
Mmh, da fallen mir gleich mehrere Sachen ein, warum das nicht gut ist:
1) der Sentinel (0) in der LUT zu verwenden ist sehr gefährlich
2) woraus kann man die Art des Intervalls (geschlossen, links-offen,
rechts-offen) erkennen? Unklar.
3) globale Variablen (als return) (war hoffentlich ein Versehen)
4) in vielen Fällen ist der Datentyp int in der LUT nicht passend
5) der Typ der Iterationsvariable i als int ist auch ungünstig
6) der Code ist nicht allgemeingültig:
6a) der Name ist schlecht gewählt
6b) kann nur mit int's arbeiten
Stefan schrieb:> Mark W. schrieb:>> Ich bin gerade dabei fuer 30 ifs aus 150 Zeilen 30 zu machen.>> In diesem konkreten Fall kann man auch fünf daraus machen, etwa>>
1
> let range = output_mV div 100
2
> var o = range + 5
3
> if range == 0:
4
> dec(o)
5
> let u = o + 1
6
>
>> Zunächst den Bereich auf Integer-Werte abzubilden ist immer eine gute> Idee, dann kann man die benötigten Zahlenwerte einfach in einem ARRAY> ablegen.
Auch das halte ich für nicht gut:
1) das geht nur für reguläre, benachbarte Intervalle
2) auch hier ist die Art des Intervalls unklar bzw. im Code versteckt.
3) imperativer Code, der seine Bedeutung schlecht offenbart, weil in
einzelnen Statements versteckt.
4) well, basic ...
Wilhelm M. schrieb:> Auch das halte ich für nicht gut:
Nö gut nicht unbedingt, daher schrieb ich ja auch
>In diesem konkreten Fall kann man auch fünf daraus machen, etwa
Man sollte halt nur wissen dass man es machen kann. Wenn man sicher ist,
dass das Schema diese konkrete Form beibehält, so ist es nicht unbedingt
schlecht und liefert guten ausführbaren Code. Und der Fall, dass man aus
einem Integer-Ausgangswert einfach Indizes 0, 1, 2, ... machen kann
kommt nicht so selten vor, dann kann man damit leicht auf eine Tabelle
in Form eines Arrays zugreifen.
Wilhelm M. schrieb:> if ((value >= 0) && (value < 10)) {> result = 0;
Da value ein uint8_t ist, trifft die Bedingung >= 0 immer zu.
In den folgenden Else-Zweigen ist der >= -Vergleich jeweils überflüssig,
denn wenn die Bedingung nicht zutrifft, trifft der jeweils vorhergehende
Vergleich zu.
Damit fällt
Das sind dann immer zusammenhängende, also angrenzende Intervalle. Und
das erste Intervall ist [-INT_MAX, 10[.
Ich bin mir nicht sicher, ob das beim TO immer gegeben ist. Und falls
man von der impliziten Sortierung abweicht, wird es falsch.
Rufus Τ. F. schrieb:> Wilhelm M. schrieb:> Und das erste Intervall ist [-INT_MAX, 10[.>> Nein. Welchen Datentyp hat "value"?
Selbst wenn es int wäre, wäre -INT_MAX nicht das Minimum... Außer auf
Plattformen die das 1er-Komplement nutzen.
Rufus Τ. F. schrieb:> Wilhelm M. schrieb:>> Und das erste Intervall ist [-INT_MAX, 10[.>> Nein. Welchen Datentyp hat "value"?
Ja stimmt: ich hatte es vorher mit int geschrieben ...
Und natürlich wird der unnötige Vergleich vom Compiler wegoptimiert.
Der exemplarische C-Code war eher dazu gedacht, die Analogie zum
generischen Code darzustellen.
Dr. Sommer schrieb:> Rufus Τ. F. schrieb:>> Wilhelm M. schrieb:>> Und das erste Intervall ist [-INT_MAX, 10[.>>>> Nein. Welchen Datentyp hat "value"?>> Selbst wenn es int wäre, wäre -INT_MAX nicht das Minimum... Außer auf> Plattformen die das 1er-Komplement nutzen.
Stimmt auch. Bezogen auf int natürlich [INT_MIN, 10[.
Und es gibt noch einen Unterschied: da die Parameterübergabe an die
lookup<>() Funktion per-value erfolgt, wird das volatile nur einmal
gelesen. Im C-Code erfolgt der Zugriff dementsprechend in jedem if-stmt.
Wenn das nicht gewollt ist, dann sollte man in C auch eine Funktion
schreiben und die Intervallgrenzen als Array übergeben (wurde oben schon
mal gepostet mit dem Problem des sentinels) oder eben:
militanter Zeilensparer schrieb:> if (output_mv >= 400) {> u = o = 0;> } else {> o = (output_mv / 100) * 2 + 2;> u =o + 1.;> }
Du bist noch nicht militant genug:
u = o = 0;
if (output_mv < 400) {
o = (output_mv / 100) * 2 + 2;
u =o + 1;
}
Wilhelm M. schrieb:> if (output_mv < 400) u = (o = (output_mv / 100) * 2 + 2) + 1;
Stimmt. Die Aufgabe war ja nicht nur Zeilen zu sparen, sondern auch
unleserlich zu schreiben.
Wilhelm M. schrieb:> z.B. auf AVR wesentlich größeren Code als:
Ist überhaupt kein Wunder, wenn Du ihm mit "volatile" die Fußfesseln
anlegst. Er muß dann für jeden Vergleich und sei er noch so überflüssig,
die Variable neu vom RAM einlesen. Optimieren ist da absolut verboten.
Schreib es als Funktion um, mit Argument und Returnwert.
Peter D. schrieb:> Wilhelm M. schrieb:>> z.B. auf AVR wesentlich größeren Code als:>> Ist überhaupt kein Wunder, wenn Du ihm mit "volatile" die Fußfesseln> anlegst. Er muß dann für jeden Vergleich und sei er noch so überflüssig,> die Variable neu vom RAM einlesen. Optimieren ist da absolut verboten.> Schreib es als Funktion um, mit Argument und Returnwert.
Lies die vorherigen Beiträge: hatte ich oben schon beschrieben
(allerdings eben nicht als Funktion in C, denn das hatte der TO auch
nicht. Zu den Problemen der geposteten Funktion mit Array der
Intervallgrenzen hatte ich auch schon etwas geschrieben).
Mark W. schrieb:> Ging mir hier um die Uebersichtlichkeit
Das passt aber nicht zu deiner eigenen Aufgabe:
Re: Code unleserlich schreiben um Zeilen zu sparen.
Erwin D. schrieb:> Mark W. schrieb:>> Ging mir hier um die Uebersichtlichkeit>> Das passt aber nicht zu deiner eigenen Aufgabe:> Re: Code unleserlich schreiben um Zeilen zu sparen.
Ja, ich gebe zu die Ueberschrift war etwas falsch ausgedrueckt.
Statt "unleserlich" koennte ich auch "abweichend von der Norm"
geschrieben haben. Das traefe es dann besser.
Aber der Post hat sich fuer mich gelohnt, ich habe viele verschiedene
Sreibweisen fuer eine Aufgabe gesehen.
Danke nochmal an alle Beteiligten.
Code "kurz" und "unleserlich" schreiben muss nicht immer paarweise
auftreten. Oftmals fällt eine Codepassage in sich zusammen, wenn man
sich mal Gedanken macht, und wird gleichzeitig einfacher verständlich.
Leider wird Code oftmals nur "hingerotzt"...
Mark W. schrieb:> Ja, ich gebe zu die Ueberschrift war etwas falsch ausgedrueckt.> Statt "unleserlich" koennte ich auch "abweichend von der Norm"
Wollte ich auch gerade schreiben. Und ja, der Code wird (bei
vorausgesetzter, geeigneter IDE) leserlicher, wenn das komplette if im
Blocksatz in eine Zeile gequetscht wird. Nur dann kann man überhaupt mit
dem Auge erkennen, ob
- eine Systematik besteht
- die Änderungen der Werte gleichen Mustern folgen
- Schreibfehler dazwischen gerutscht sind (z.B. u und o bei einem if
vertauscht)
- welche (der hier vorgestellten) Optimierungen möglich/nötig/sinnvoll
sind.
Da wir Code sowieso nur für uns (und nicht für den Compiler) schreiben,
sollte eine Optimierung (zu einer Formel) auch nur erfolgen, wenn es
dadurch noch besser lesbar wird! (Abgesehen von den ganz wenigen Fällen,
in denen Speicher- oder Zeit-Optimierung notwendig ist)
g457 schrieb:> Wie schon geschurbt wurde ist das non-standard. Würde hierzufirma wohl> auch (berechtigterweise) zum Rauswurf führen.
Höhöhö, die rauswerfen dürfen, haben meistens nicht das notwendige
Fachwissen.
Achim S. schrieb:> Da wir Code sowieso nur für uns (und nicht für den Compiler) schreiben,> sollte eine Optimierung (zu einer Formel) auch nur erfolgen, wenn es> dadurch noch besser lesbar wird!
Wenn eine Systematik besteht, ist mir eine Formel allemal lieber als
eine lange Reihe von 'if's oder 'case's. Nicht nur aus
Optimierungsgründen, sondern auch von der Verständlichkeit her. Muss ich
sonst ja erst alles durchlesen, um zu erkennen, ob die Systematik
durchgehend ist.
Außerdem widerspricht es dem Prinzip "Don't repeat yourself", was sich
auch auf die Wartbarkeit auswirkt.
Wenn die Werte keine Systematik haben, aber ein Raster (hier 100) würde
ich ein Array nehmen und die Werte in die Deklaration schreiben.
o = arr[ output_mv /100];
u = o + 1;
Jobst Q. schrieb:> Wenn die Werte keine Systematik haben, aber ein Raster (hier 100) würde> ich ein Array nehmen und die Werte in die Deklaration schreiben.>> o = arr[ output_mv /100];> u = o + 1;
Das ist doch genau der oben beschrieben LUT Ansatz: Du hast eine
Wertemenge, die bestimmt die Anzahl der Einträge in der Tabelle, und Du
eine Abbildung des Definitionsbereiches auf die Indizes der Tabelle.
Die spannende Frage ist, wie kommt man auf die Eingangsabbildung und wie
füllt man die Tabelle, und welche Datentypen sind sinnvoll. Das macht
der generische Code, den ich oben mal gepostet hatte.
Wilhelm M. schrieb:> volatile uint8_t result;> volatile uint8_t value = 100;>> constexpr auto limits = std::make_array<uint8_t>(0, 10, 20, 40, 80,> 160);> constexpr auto intervals = make_intervals<RightOpen, Adjacent>(limits);>> int main() {> auto index = lookup(value, intervals);> if (index) {> result = *index;> }> }
Ich krieg da nur Fehler:
1
test.cpp:6: error: expected constructor, destructor, or type conversion before 'auto'
2
test.cpp:7: error: expected constructor, destructor, or type conversion before 'auto'
3
test.cpp: In function 'int main()':
4
test.cpp:10: error: ISO C++ forbids declaration of 'index' with no type
5
test.cpp:10: error: 'intervals' was not declared in this scope
6
test.cpp:10: error: 'lookup' was not declared in this scope
7
test.cpp:12: error: invalid type argument of 'unary *'
Oliver S. schrieb:> Das Ergebnis von gcc -v wäre wohl eher interessant.
ja, wobei heutzutage eher das Flag -std=...
> Wobei dem Quelltext wohl schon das ein- oder andere headerfile fehlt.
Worauf ich damit hinweisen wollte ;-)
Wilhelm M. schrieb:> constexpr auto limits = std::make_array<uint8_t>(0, 10, 20, 40, 80, 160);> constexpr auto intervals = make_intervals<RightOpen, Adjacent>(limits);
Mir gefiele diese Lösung prinzipiell ganz gut, wenn ich wüsste, was ich
für make_intervals includen muss? Auch make_array ist nicht
Standard, aber immerhin in experimental/array bzw.im Namespace
std::experimental enthalten. make_intervals hingegen kann ich weder in
der (experimentellen) Standardbibliothek noch in den Boost-Bibliotheken
finden.
Wilhelm ist vermutlich mit einem pre-Alpha gcc 10 unterwegs, und nutzt
C++27. PeDa kommt mit seinem erprobten 3er gcc, und alle anderen hängen
irgendwo dazwischen.
Da kommt es schon mal zu Unverständlichkeiten ;)
Oliver
Yalu X. schrieb:> Mir gefiele diese Lösung prinzipiell ganz gut, wenn ich wüsste, was ich> für make_intervals includen muss? Auch make_array ist nicht> Standard, aber immerhin in experimental/array bzw.im Namespace> std::experimental enthalten. make_intervals hingegen kann ich weder in> der (experimentellen) Standardbibliothek noch in den Boost-Bibliotheken> finden.
Oh, das hört sich jetzt so ein bisschen Arduino-like an: ich kann die
lib nicht finden...
Oliver S. schrieb:> Wilhelm ist vermutlich mit einem pre-Alpha gcc 10 unterwegs, und nutzt> C++27.
Mmh, C++27 wird es wohl nicht geben.
>PeDa kommt mit seinem erprobten 3er gcc, und alle anderen hängen> irgendwo dazwischen.>> Da kommt es schon mal zu Unverständlichkeiten ;)
Ok, dann versuche ich das mal aufzuklären. Ich poste einfach mal den
ganzen Code. Allerdings auch dann wird es wohl nicht klappen, ihr
braucht nämlich ein constexpr sort<>() (hier: Util::sort<>()), das
std::sort<>() ist nicht constexpr. Das es zur Compilezeit verwendet
wird, tut es ein Bubblesort ;-) (das zu schreiben überlasse ich gerade
Euch).
Alles andere ist schnell heruntergetippt, ein paar Fälle habe ich auch
ausgelassen, manche Namen sind nicht gut. Man könnte es schöner machen.
Es soll ja nur das Prinzip zeigen...
Allerdings sollte man m.E. auch eine andere Variante realisieren, die
nur mit elementar-konstanten Grenzen arbeitet. Denn diese hier kann ja
auch mit non-constexpr arbeiten.
*Thema verfehlt!*
Die Aufgabe hiess, Code unleserlich schreiben, um Zeilen zu sparen!
Ernsthaft: es ist beeindruckend, was mit modernem C++ alles geht. Aber
glaubst Du wirklich, dass das die µC-Programmierung - in Zeiten, wo der
Durchschnittsprogrammierer kaum eine Arduino-loop() fehlerfrei hinkriegt
- voranbringt?
Markus F. schrieb:> *Thema verfehlt!*
Prinzip nicht verstanden!
> Die Aufgabe hiess, Code unleserlich schreiben, um Zeilen zu sparen!
Es sind im Code des Klienten (!) 3 Zeilen. Und das bei beliebig vielen
Intervallen, die geschlossen/halboffen sein können und benachbart oder
nicht, und auch noch für beliebige Datentypen.
> Ernsthaft: es ist beeindruckend, was mit modernem C++ alles geht. Aber> glaubst Du wirklich, dass das die µC-Programmierung - in Zeiten, wo der> Durchschnittsprogrammierer kaum eine Arduino-loop() fehlerfrei hinkriegt> - voranbringt?
Ja, davon bin ich überzeugt.
Wilhelm M. schrieb:> Markus F. schrieb:>> Ernsthaft: es ist beeindruckend, was mit modernem C++ alles geht. Aber>> glaubst Du wirklich, dass das die µC-Programmierung - in Zeiten, wo der>> Durchschnittsprogrammierer kaum eine Arduino-loop() fehlerfrei hinkriegt>> - voranbringt?>> Ja, davon bin ich überzeugt.
Vielleicht wäre es gut in den Beispielen die C++-Version und die
Minimum-Compilerversion anzugeben. Im obigen Fall C++14/gcc4.9. Es gibt
ja auch noch Leute, die Winavr2010(gcc4.3 oder so) benutzen, das
behindert diese dann beim Mitüberzeigtsein.
Wobei gcc7.3 komplett C++17 kann, man also nicht wirklich Angst vor
Alpha-Versionen haben muß, wenn man ganz up TO Date sein will,
z.B. mit "if constexpr"
Wilhelm M. schrieb:> Mmh, C++27 wird es wohl nicht geben.
Das war schon so gemeint, wie es da steht. 20, 23, 26, dazu auf dem Weg
dahin ein Jahr Verspätung, das passt schon.
Oliver
Wilhelm M. schrieb:> Yalu X. schrieb:>> Mir gefiele diese Lösung prinzipiell ganz gut, wenn ich wüsste, was ich>> für make_intervals includen muss? Auch make_array ist nicht>> Standard, aber immerhin in experimental/array bzw.im Namespace>> std::experimental enthalten. make_intervals hingegen kann ich weder in>> der (experimentellen) Standardbibliothek noch in den Boost-Bibliotheken>> finden.>> Oh, das hört sich jetzt so ein bisschen Arduino-like an: ich kann die> lib nicht finden...
Naja, ich dachte, ich hätte da vielleicht irgendein neues C++17- oder
C++20-Feature verpasst, was aber offensichtlich nicht der Fall ist, da
du make_intervals und lookup selber geschrieben hast.
Damit hat aber deine Lösung in meinen Augen ganz gewaltig an Eleganz
verloren. Natürlich kann man jedes noch so komplexe Problem mit einem
Ein- oder Zweizeiler lösen, wenn diese Zeilen aus Aufrufen von
Funktionen bestehen, die erst noch entwickelt werden müssen. Im
konkreten Fall hast du ein Problem, das man auf klassische Weise in 1
bis 10 Codezeilen (je nachdem, ob die Schwellwerte äquidistant sind oder
nicht) umsetzen würde, durch ein Konstrukt gelöst, das zugegebenermaßen
ganz pfiffig ist, dafür aber 70 Codezeilen umfasst und dabei noch nicht
einmal Dinge wie die Optimierungsmöglichkeit im Fall von äquidistanten
Schwellwerten nutzt.
Wenn man bedenkt, dass der zusätzliche Code auch getestet, gedebugt und
dokumentiert werden muss und dass man diese Intervallsuche nur relativ
selten benötigt, hat man mit deiner Lösung außer Erkenntnisgewinn nichts
gewonnen und stattdessen zusätzlichen Entwicklungsaufwand verursacht.
Ganz anders läge der Fall, wenn die Funktionen make_interval und
lookup durch die Standardbibliothek bereitgestellt würden. Dann würde
der Aufwand für Implementierung, Test, Debugging und Dokumentation
weitgehend entfallen, so dass die Lösung fast jeder selbstgeschriebenen
Variante vorzuziehen wäre.
Das ist auch der Grund, warum ich nachgefragt habe. Obwohl ich deine
negative Antwort eigentlich schon erwartet habe, bin ich jetzt doch ein
ganz klein wenig enttäuscht :)
PS:
Wilhelm, mal Hand aufs Herz: Glaubst du, der TE hätte es von sich aus
wirklich geschafft, nach dem Lesen deines Beitrags vom 02.06.2018
09:44 die Funktionen make_intervals und lookup selber zu schreiben?
Mark W. schrieb:> Naja, zum Glueck bin ich ja kein Software-Entwickler.
PPS:
Wilhelm M. schrieb:> a) benutze Algorithmen / Funktionen, keine expl. IterationenWilhelm M. schrieb:> for(typename Limits::size_type n = 0; n < in.size(); ++n) {> ...> for(typename Limits::size_type n = 0; n < in.size(); ++n) {> ...> for(typename Limits::size_type n = 0; n < in.size(); ++n) {> ...Wilhelm M. schrieb:> b) benutze Algorithmen / Funktionen, keine expl. AlternativenWilhelm M. schrieb:> if constexpr(std::is_same_v<Type, RightOpen>) {> ...> if constexpr(std::is_same_v<Type, RightOpen>) {> ...> if constexpr(!std::is_same_v<Construct, Adjacent>) {> ...> if (intervals[n].includes(value)) {> ...
Yalu X. schrieb:> Wilhelm M. schrieb:>> b) benutze Algorithmen / Funktionen, keine expl. Alternativen>> Wilhelm M. schrieb:>> if constexpr(std::is_same_v<Type, RightOpen>) {>> ...>> if constexpr(std::is_same_v<Type, RightOpen>) {>> ...>> if constexpr(!std::is_same_v<Construct, Adjacent>) {>> ...>> if (intervals[n].includes(value)) {>> ...
"if constexpr" ist nicht so leicht durch anderes ersetzbar (außer
kompliziertem Template-Zeugs)
BTW, das hatte ich beim Überfliegen gar nicht bemerkt, also IST das
C++-17.
Mark W. schrieb:> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?> Oder geht das gar nicht?> if(output_mV < 100){o = 4; u = 5;}
Ich mag soetwas garnicht. Bei mir (in VBA) bekommt jede Variable eine
eigene Deklarationszeile und einen sprechenden Namen. Damit ich immer
weiss welche Variable was macht.
Mark W. schrieb:> Ging mir hier um die Uebersichtlichkeit, weil man da beim Schreiben> weniger scrollen muss.
Übersichtlichkeit erreicht man durch Einrücken. Oder durch Auslagern von
Codeteilen in Rückgabefunktionen. Zumindest in VBA ist es einfach. Wenn
ich eine umfangreiche Userform erstellen muss lagere ich die Prozeduren
in Module aus. Jede Prozedur in ein eigenes Modul. Das Modul bekommt den
Namen der Prozedur, wobei ein "mdl" davorgesetzt wird (Modul und
Prozedur dürfen nicht den selben Namen tragen, sonst kommt es zu
Konflikten). Die Callbacks im Userform-Codemodul rufen dann nur die
Prozeduren auf und sind somit einzeilig. Ergebnis ist eine gute
Übersichtlichkeit die ich auch noch nach Jahren problemlos
nachvollziehen kann, und scrollen muss ich dann auch nicht mehr (es sei
denn der Code ist etwas länger).
René H. schrieb:> Oder durch Auslagern von> Codeteilen in Rückgabefunktionen
Das gilt nicht "absolut". Ganz grob, bei einem Anfänger-Projekt von 1000
Zeilen sind ~10 Files je ~10 Funktionen je ~10 Zeilen vielleicht
übersichtlich. Bei 1E5 Codezeilen würde man die 30 Zeilen des TO NICHT
auslagern (wenn sie nur einmal gebraucht werden). Dann sind auch
Funktionen mit 100 oder 1000 Zeilen normal und Tabellen (Blocksatz) ein
Mittel der Wahl.
Achim S. schrieb:> Dann sind auch Funktionen mit 100 oder 1000 Zeilen normal und Tabellen> (Blocksatz) ein Mittel der Wahl.
Das ist eher Spaghetti Code. Gerade bei großen Projekten sollten
Funktionen nicht so lang werden. Besser ist es, viele kleine Funktionen
(ca 10 Zeilen) zu haben, die genau einen Aspekt bearbeiten und alles
andere ggf. delegieren. So werden sie viel leichter verständlich. Diese
typischen Riesen-Algorithmen in Anfänger-Code lassen sich meist in viele
kleine Einheiten aufteilen. Die kann man dann auch wieder verwenden.
Große Tabellen sollten auch eher die Ausnahme sein. Oft lassen die sich
auch automatisch per constexpr generieren.
Carl D. schrieb:> Wilhelm M. schrieb:>> Markus F. schrieb:>>> Ernsthaft: es ist beeindruckend, was mit modernem C++ alles geht. Aber>>> glaubst Du wirklich, dass das die µC-Programmierung - in Zeiten, wo der>>> Durchschnittsprogrammierer kaum eine Arduino-loop() fehlerfrei hinkriegt>>> - voranbringt?>>>> Ja, davon bin ich überzeugt.>> Vielleicht wäre es gut in den Beispielen die C++-Version und die> Minimum-Compilerversion anzugeben.
Ja, sicher: ab C++17, also -std=c++17 oder -std=c++2a
> Im obigen Fall C++14/gcc4.9. Es gibt> ja auch noch Leute, die Winavr2010(gcc4.3 oder so) benutzen, das> behindert diese dann beim Mitüberzeigtsein.AVR wird eher schwierig, da es keine libstdc++ offiziell für die
8-Bitter gibt. Ich habe meine eigene Realisierung, die bestimmte
Optimierungen bzgl. der intern verwendeten DT macht.
> Wobei gcc7.3 komplett C++17 kann, man also nicht wirklich Angst vor> Alpha-Versionen haben muß, wenn man ganz up TO Date sein will,> z.B. mit "if constexpr"
Oh, seit 02.05.18 haben wir auch 8.1 released, der kann auch
familiar-template-syntax für generische lambdas. Das finde ich sehr
schön.
Oliver S. schrieb:> Wilhelm M. schrieb:>> Mmh, C++27 wird es wohl nicht geben.>> Das war schon so gemeint, wie es da steht. 20, 23, 26, dazu auf dem Weg> dahin ein Jahr Verspätung, das passt schon.
Der Standard wird sich nicht verspäten, das wird C++26. Allerdings
werden wohl einige Compiler wieder notorisch hinter hinken.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Yalu X. schrieb:>>> Mir gefiele diese Lösung prinzipiell ganz gut, wenn ich wüsste, was ich>>> für make_intervals includen muss? Auch make_array ist nicht>>> Standard, aber immerhin in experimental/array bzw.im Namespace>>> std::experimental enthalten. make_intervals hingegen kann ich weder in>>> der (experimentellen) Standardbibliothek noch in den Boost-Bibliotheken>>> finden.>>>> Oh, das hört sich jetzt so ein bisschen Arduino-like an: ich kann die>> lib nicht finden...>> Naja, ich dachte, ich hätte da vielleicht irgendein neues C++17- oder> C++20-Feature verpasst, was aber offensichtlich nicht der Fall ist, da> du make_intervals und lookup selber geschrieben hast.>> Damit hat aber deine Lösung in meinen Augen ganz gewaltig an Eleganz> verloren. Natürlich kann man jedes noch so komplexe Problem mit einem> Ein- oder Zweizeiler lösen, wenn diese Zeilen aus Aufrufen von> Funktionen bestehen, die erst noch entwickelt werden müssen.
Ja, das sollte man auch tun. Dann seine Testfälle dafür schreiben und
diese Funktion in seinen Werkzeugkasten legen.
> Im> konkreten Fall hast du ein Problem, das man auf klassische Weise in 1> bis 10 Codezeilen (je nachdem, ob die Schwellwerte äquidistant sind oder> nicht) umsetzen würde, durch ein Konstrukt gelöst, das zugegebenermaßen> ganz pfiffig ist, dafür aber 70 Codezeilen umfasst
Dafür kann dieses Konstrukt eben auch mit allen Intervallarten und allen
Datentypen umgehen. Das ist schon ein wesentlicher Unterschied.
> und dabei noch nicht> einmal Dinge wie die Optimierungsmöglichkeit im Fall von äquidistanten> Schwellwerten nutzt.
Aus das wäre kein Problem, statt Intervalle anzugeben, eine
Abbildungsfunktion anzugeben. (BTW: wobei man bei der Indizierung eines
rohen Arrays zumindest mal Assertionen über die Indizes einbauen sollte,
und nicht wie es oben schon mal gepostet wurde.)
> Wenn man bedenkt, dass der zusätzliche Code auch getestet, gedebugt und> dokumentiert werden muss
Das ist kein Argument, denn Dein Code muss auch getestet, korrigiert und
dokumentiert werden. Allerdings mache ich das in meiner Bibliothek
einmal und Du in jeder Anwendung immer wieder.
> und dass man diese Intervallsuche nur relativ> selten benötigt, hat man mit deiner Lösung außer Erkenntnisgewinn nichts> gewonnen und stattdessen zusätzlichen Entwicklungsaufwand verursacht.
Das ist eine Milchmädchenrechnung: um Copy-n-Paste Lösungen vorzubeugen,
sollte man versuchen, so viel wie möglich zu generalisieren und aus
Bibliotheken zu entnehmen bzw. eben den eigenen Bibliotheken
hinzuzufügen. Der Aufwand hat sich im Gesamten schnell wieder
amortisiert.
> Ganz anders läge der Fall, wenn die Funktionen make_interval und> lookup durch die Standardbibliothek bereitgestellt würden. Dann würde> der Aufwand für Implementierung, Test, Debugging und Dokumentation> weitgehend entfallen, so dass die Lösung fast jeder selbstgeschriebenen> Variante vorzuziehen wäre.
Ja, aber die libstdc++ ist nicht allumfassend und wird es auch nie sein.
Vielleicht gibt es auf dieser Welt eine andere vertrauensvolle
Bibliothek, die das realisiert - ich habe nicht danach gesucht.
Aber: schreibst Du keine Bibliotheken für Deine Projekte bzw.
Anwendungsdomäne?
> Das ist auch der Grund, warum ich nachgefragt habe. Obwohl ich deine> negative Antwort eigentlich schon erwartet habe, bin ich jetzt doch ein> ganz klein wenig enttäuscht :)
Du bist enttäuscht, dass die libstdc++ dafür keine mundgerechte Lösung
parat hat? Man könnte es mit adjacent_find<>() machen ... allerdings ist
das nicht constexpr, was ja hier hilfreich wäre.
> PS:>> Wilhelm, mal Hand aufs Herz: Glaubst du, der TE hätte es von sich aus> wirklich geschafft, nach dem Lesen deines Beitrags vom 02.06.2018> 09:44 die Funktionen make_intervals und lookup selber zu schreiben?
Das kann und will ich nicht beurteilen. Aber es könnte sein, das der TE
und einige andere etwas an Erkenntnis aus dieser Diskussion mitnimmt.
Und sei es auch nur, neugierig auf Neues zu sein.
> PPS:>> Wilhelm M. schrieb:>> a) benutze Algorithmen / Funktionen, keine expl. Iterationen>> Wilhelm M. schrieb:>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>> ...>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>> ...>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>> ...
Dies bezieht sich immer auf den Code der Klienten. Wie meinst Du denn,
ist z.B. ein std::copy<>() implementiert?
Es ist wichtig, die Grenze zwischen Code des Klienten und den
Bibliotheken zu beachten. Im obigen Beispiel war es eigentlich klar.
Also nochmal: das meiste ist bibliotheksbezogen, nur make_array,
make_intervals und lookup ist für den Klienten.
> Wilhelm M. schrieb:>> b) benutze Algorithmen / Funktionen, keine expl. Alternativen>> Wilhelm M. schrieb:>> if constexpr(std::is_same_v<Type, RightOpen>) {>> ...>> if constexpr(std::is_same_v<Type, RightOpen>) {>> ...>> if constexpr(!std::is_same_v<Construct, Adjacent>) {>> ...>> if (intervals[n].includes(value)) {>> ...
Auch hier gilt natürlich das oben Gesagte: auch ein std::find<>() wird
nicht ohne eine Laufzeit-Alternative auskommen. Hier ist es allerdings
kein Laufzeit-if, sondern eine bedingte template-Instanziierung (bis auf
das letzte zitierte if).
Wilhelm M. schrieb:> Ja, sicher: ab C++17, also -std=c++17 oder -std=c++2a>>> Im obigen Fall C++14/gcc4.9. Es gibt>> ja auch noch Leute, die Winavr2010(gcc4.3 oder so) benutzen, das>> behindert diese dann beim Mitüberzeigtsein.>> AVR wird eher schwierig, da es keine libstdc++ offiziell für die> 8-Bitter gibt. Ich habe meine eigene Realisierung, die bestimmte> Optimierungen bzgl. der intern verwendeten DT macht.
Kenn ich ;-) Macht es schwierig die oft verlangten Beispiele zu liefern,
ohne gleich ein dickes Zip-File dazupacken zu müssen. Ich hab mir bisher
immer Dinge, die mir gefehlt haben, entweder aus dem Original geliehen,
oder wenn's Triviales war, einfach selber geschrieben.
> Oh, seit 02.05.18 haben wir auch 8.1 released, der kann auch> familiar-template-syntax für generische lambdas. Das finde ich sehr> schön.
Dann wird's noch schwieriger, denn dann wollen/müssen die ja auch noch
den "Selbstbau"-Compiler dazu haben.
Es ging ja darum, den Code "unleserlich" zu schreiben ;-)
Deswegen habe ich gerade nochmal eine Variante erstellt, die
ausschließlich statisch arbeitet, d.h. sie ist das direkte Äquivalent zu
hardcoded if-stmts. Allerdings immer noch mit dem Vorteil der
unterschiedlichen Intervallarten und Datentypen.
Strengt Euch nicht an, das bei Euch zum Compilieren zu bekommen: es
fehlt Euch die Meta-Programm-Bibliothek im namespace Meta. Aber
vielleicht kann man trotzdem erkennen, was gemacht wird. Na ja, das
Wesentliche ist eigentlich die zentrale fold-expression.
Carl D. schrieb:>> Oh, seit 02.05.18 haben wir auch 8.1 released, der kann auch>> familiar-template-syntax für generische lambdas. Das finde ich sehr>> schön.> Dann wird's noch schwieriger, denn dann wollen/müssen die ja auch noch> den "Selbstbau"-Compiler dazu haben.
Im aktuellen MinGW ist doch aber auch der offizielle gcc 8.1 drin.
Wilhelm M. schrieb:> Ich poste einfach mal den ganzen Code.
Na das ist ja ne ganze Menge Holz, was da zusätzlich benötigt wird.
Ich denke nicht, daß es sich lohnt, immer sofort ne Lib zu schreiben,
die Aufgaben sind zu vielfältig.
Hier noch ein kleines praktisches Beispiel in plain C aus meiner
Tastenabfrage mit ADC. Die Suchtabelle ist nichtlinear und wird mit dem
Ohmschen Gesetz berechnet. Es wird die Bitstelle der gedrückten Taste
ermittelt.
Wilhelm M. schrieb:> Aber: schreibst Du keine Bibliotheken für Deine Projekte bzw.> Anwendungsdomäne?
Doch, nur ich habe mir (aus gutem Grund) abgewöhnt, Funktionen oder
Klassen mit Zusatzfeatures zu schreiben, deren spätere Verwendung
ungewiss ist. Anders ausgedrückt, produziere ich keinen Code "auf
Halde". In deinem Beispiel wäre die Option Disjoint so ein Fall. Da
mir dafür kein konkretes Anwendungsbeispiel einfällt, würde ich das
Feature auch nicht implementieren.
Wilhelm M. schrieb:> Du bist enttäuscht, dass die libstdc++ dafür keine mundgerechte Lösung> parat hat? Man könnte es mit adjacent_find<>() machenadjacent_find passt wohl nicht so richtig für das Problem des TE, aber
was spricht gegen find_if? Für die Zukunft schöner fände ich find_if
aus experimental/ranges/algorithm, da man dort das Array mit den
Schwellwerten direkt (ohne den hässlichen Umweg über den first- und
last-Iterator) übergeben kann.
> ... allerdings ist das nicht constexpr, was ja hier hilfreich wäre.
Das empfinde ich nicht als Nachteil, das der zu untersuchende Wert (beim
TE output_mV) i.Allg. sowieso variabel ist.
Wilhelm M. schrieb:>> Wilhelm M. schrieb:>>> a) benutze Algorithmen / Funktionen, keine expl. Iterationen>>>> Wilhelm M. schrieb:>>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>>> ...>>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>>> ...>>> for(typename Limits::size_type n = 0; n < in.size(); ++n) {>>> ...>> Dies bezieht sich immer auf den Code der Klienten. Wie meinst Du denn,> ist z.B. ein std::copy<>() implementiert?
Für mich ist eine Iteration nur dann implizit, wenn ich sie nicht selber
geschrieben habe. Aus der Sicht des TE, der deinen Code benutzt, sind
die Iterationen tatsächlich implizit. Als du dieses schriebst:
Wilhelm M. schrieb:> a) benutze Algorithmen / Funktionen, keine expl. Iterationen
hatte der TE aber noch gar keinen Zugriff auf deinen Code, weswegen er
die Funktionen selber implementieren hätte müssen. Damit wären die
Iterationen für ihn explizit, denn alleine das Verlagern einer Iteration
in einen anderen Code-Abschnitt macht diese noch lange nicht implizit.
Wilhelm M. schrieb:> Strengt Euch nicht an, das bei Euch zum Compilieren zu bekommen:
Das war auch nur der Versuch, anhand des Assemblerlistings
herauszufinden, was Dein Programm eigentlich macht. Beim Lesen der
Sourcen erschließen sich mir nur wenige Teilaspekte, aber nicht der
eigentliche Ablauf.
Peter D. schrieb:> Hier noch ein kleines praktisches Beispiel in plain C aus meiner> Tastenabfrage mit ADC. Die Suchtabelle ist nichtlinear und wird mit dem> Ohmschen Gesetz berechnet. Es wird die Bitstelle der gedrückten Taste> ermittelt.
Ich habe Deinen Code mal ergänzt zu:
Wie Du siehst, habe ich einmal genau Deinen Code mit der Taste als
Bit-Muster und einmal eine günstigere Variante mit der Taste als Nummer
erstellt.
Hier die Zahlen jeweils bezogen auf AVR m328:
Meine Variante : 192 flash, 2 data
Deine Variante i : 210 flash, 2 data
Deine Variante ii: 214 flash, 2 data
Bei mir erstellt Converter<> mit Hilfe des Generator ein
PgmArray<Boundary<uint8_t, RightOpen>>. Wie der Name schon sagt, liegen
die Daten des PgmArray im ProgMem des AVR.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Du bist enttäuscht, dass die libstdc++ dafür keine mundgerechte Lösung>> parat hat? Man könnte es mit adjacent_find<>() machen>> adjacent_find passt wohl nicht so richtig für das Problem des TE,
Passt genau, wenn man unzusammenhängende Intervalle hat (Option
Disjoint). Falls man in dem Beispiel von Peter D. noch eine Hysterese
einbauen wollte.
> aber> was spricht gegen find_if?
Passt nur für zusammenhängende Intervalle.
> Für die Zukunft schöner fände ich /find_if/> aus experimental/ranges/algorithm, da man dort das Array mit den> Schwellwerten direkt (ohne den hässlichen Umweg über den first- und> last-Iterator) übergeben kann.
Das ist ein Einzeiler wenn es nur um die Iteratoren geht.
>> ... allerdings ist das nicht constexpr, was ja hier hilfreich wäre.>> Das empfinde ich nicht als Nachteil, das der zu untersuchende Wert (beim> TE output_mV) i.Allg. sowieso variabel ist.
constexpr schränkt das ja auch nicht ein, es bietet eben nur die
Möglichkeit in einem constexpr-Kontext.
> Für mich ist eine Iteration nur dann implizit, wenn ich sie nicht selber> geschrieben habe. Aus der Sicht des TE, der deinen Code benutzt, sind> die Iterationen tatsächlich implizit. Als du dieses schriebst:>> Wilhelm M. schrieb:>> a) benutze Algorithmen / Funktionen, keine expl. Iterationen>> hatte der TE aber noch gar keinen Zugriff auf deinen Code, weswegen er> die Funktionen selber implementieren hätte müssen. Damit wären die> Iterationen für ihn explizit, denn alleine das Verlagern einer Iteration> in einen anderen Code-Abschnitt macht diese noch lange nicht implizit.
Jein. Wenn er es wie gesagt in eine (eigene) Bibliothek mit
entsprechenden Tests, etc. auslagern würde, dann wäre es auch dort
implizit. Du kannst auch Klient Deines eigenen Codes sein. Das passiert
ja manchmal auch auf Umwegen.
Wilhelm M. schrieb:> Bei mir erstellt Converter<> mit Hilfe des Generator ein ...
???
Ich hab nicht die geringste Idee, welche Zeile das Array definiert und
wo die Schleife mit dem Vergleich auf "<" ist.
Und da ich es ja eh nichtmal compiliert werden kriege, bleibe ich wohl
besser bei plain C.
Ich nehme mal an, zum Compilieren ist noch ne riesen Latte von Deinen
speziellen Headern nötig, die Du leider nicht angegeben hast.
Mein Code war vollständig, d.h. er compiliert ohne weitere Header.
An plain C mag ich, daß es gut dokumentiert ist, z.B. wenn ich nach
scanf, printf usw. google.
Suche ich dagegen nach Converter, Generator, RightOpen usw., kann mir
Google nicht helfen. Das macht es natürlich schwer, solche
Schlüsselwörter zu benutzen.
Peter D. schrieb:> Suche ich dagegen nach Converter, Generator, RightOpen usw., kann mir> Google nicht helfen. Das macht es natürlich schwer, solche> Schlüsselwörter zu benutzen.
Das sind auch keine Schlüsselworte, sondern selbstgeschriebene
Funktionen. Da kann dir Google wirklich nicht weiterhelfen.
Oliver
Hier ist eine Variante von Peters Code die mittels Metaprogrammierung
das Array berechnet. Der Hauptvorteil besteht hier darin, dass man durch
eine einzige Zahl die Anzahl der Einträge bestimmen kann, und man die
genLUT-Funktion auch problemlos für beliebige andere LUT's recyclen
kann. Eleganter wär's noch die Zahlen nicht als globale Konstanten zu
übergeben sondern z.B. als template-Parameter an treshold; das sei als
Übung dem Leser überlassen :)
Der Code ist vollständig und mit C++14 kompilierbar. Selbstverständlich
ist auch C++ dokumentiert (nicht nur im Standard), und alle Dinge die
hier nicht im Code definiert sind kann man Googlen:
1
#include<iostream>
2
#include<utility>
3
#include<array>
4
#include<cstddef>
5
#include<cstdint>
6
7
staticconstexprdoubleRVCC=10.0;// 10k to VCC
8
staticconstexprdoubleRROW=1.0;// 1k between rows
9
staticconstexprdoubleRCOL=3.9;// 3k9 between colums
10
staticconstexprstd::size_tNROW=4;// number of rows
Die 0 am Ende des Arrays hab ich weggelassen; ich finde es eleganter per
THRESHOLDS.size() die Größe explizit abzufragen, so stören auch
gewünschte Nullen im Array nicht.
Oliver S. schrieb:> Das sind auch keine Schlüsselworte, sondern selbstgeschriebene> Funktionen.
Das hatte ich mir schon gedacht. Dann sind aber Codebeispiele ohne die
benötigten Funktionsdefinitionen ziemlich sinnlos. Beispiele sollten
schon nachvollziehbar sein.
Dr. Sommer schrieb:> Das ist eher Spaghetti Code. Gerade bei großen Projekten sollten> Funktionen nicht so lang werden. Besser ist es, viele kleine Funktionen> (ca 10 Zeilen) zu haben, die genau einen Aspekt bearbeiten und alles> andere ggf. delegieren.
Wenn 1E6-Zeilen in 100 Treiber zu je 1E4 Zeilen zerfallen, hast Du
recht. Ich vermute, du redest von so was.
> Diese typischen Riesen-Algorithmen in Anfänger-Code lassen sich meist> in viele kleine Einheiten aufteilen.
Auch das stimmt. Davon ist bei mir aber nicht die Rede.
> Die kann man dann auch wieder verwenden.
Auch das stimmt. Aber was soll das?
Das man eine Aufgabe auf verschiedene Arten beleuchten soll um Synergien
und Vereinfachungen zu finden, sicher. Aber irgendwie anzunehmen, dass
komplexe Dinge (und nur um die geht es hier) einfacher werden, wenn ich
sie aus ihrem Kontext reiße und diesen mnühsam wieder herstelle (bzw.
muss), zeigt doch nur, dass Du die Straße vermutlich noch nie gegangen
bist. Also nichts für ungut.
Achim S. schrieb:> Wenn 1E6-Zeilen in 100 Treiber zu je 1E4 Zeilen zerfallen, hast Du> recht. Ich vermute, du redest von so was.
Nö, auch von monolithischen Projekten. Auch da braucht man keine
1000-Zeilen-Funktionen. Die lassen sich zu 99% in handlichere Funktionen
aufteilen. Und wenn das einen "Kontext zerreißt" sind die Daten-und
Programmstrukturen wohl nicht gut konstruiert.
Achim S. schrieb:> zeigt doch nur, dass Du die Straße vermutlich noch nie gegangen> bist. Also nichts für ungut.
Ad Hominem, ich hör dir trappsen. Ja, ich hab auch mal Spaghetti-Code
geschrieben. Vor >10 Jahren... :)
Dr. Sommer schrieb:> Hier ist eine Variante von Peters Code die mittels Metaprogrammierung> das Array berechnet. Der Hauptvorteil besteht hier darin, dass man durch> eine einzige Zahl die Anzahl der Einträge bestimmen kann, und man die> genLUT-Funktion auch problemlos für beliebige andere LUT's recyclen> kann.
Warum nicht C++17? Dann sind lambdas (automatisch) constexpr. Da geht
das alles viel einfacher.
1
#include<iostream>
2
#include<utility>
3
#include<array>
4
#include<cstddef>
5
#include<cstdint>
6
7
staticconstexprdoubleRVCC=10.0;// 10k to VCC
8
staticconstexprdoubleRROW=1.0;// 1k between rows
9
staticconstexprdoubleRCOL=3.9;// 3k9 between colums
10
staticconstexprstd::size_tNROW=4;// number of rows
Allerdings haben wir damit nur die Tabelle, noch keine Verwendung dieser
als Intervallbildner oder unterschiedliche Intervallarten (was ich oben
gepostet hatte).
Macht man dieses Beispiel etwa auch noch auf einem AVR, so landet die
Tabelle im RAM, entweder im data-segment oder auf dem Stack (als local
object). Deswegen habe ich oben mit einem PgmArray gearbeitet.
Wilhelm M. schrieb:> Warum nicht C++17? Dann sind lambdas (automatisch) constexpr. Da geht> das alles viel einfacher.
Naja, die Idee war ja schon die Funktion genLUT wiederverwendbar zu
machen... :) Und das ging in C++14 halt auch. Keil und Konsorten können
auch kein C++17...
Wilhelm M. schrieb:> Allerdings haben wir damit nur die Tabelle,
Peter's Funktion ließe sich damit direkt problemlos nutzen. Wollte sie
nur nicht kopieren.
Wilhelm M. schrieb:> Macht man dieses Beispiel etwa auch noch auf einem AVR, so landet die> Tabelle im RAM, entweder im data-segment oder auf dem Stack (als local> object). Deswegen habe ich oben mit einem PgmArray gearbeitet.
Ja, sowas braucht man da auch, aber ich kenn mich mit der ganzen
AVR-Progmem-Geschichte nicht so aus, bin zu verwöhnt von ARM :)
Oliver S. schrieb:> Peter D. schrieb:>> Suche ich dagegen nach Converter, Generator, RightOpen usw., kann mir>> Google nicht helfen. Das macht es natürlich schwer, solche>> Schlüsselwörter zu benutzen.>> Das sind auch keine Schlüsselworte, sondern selbstgeschriebene> Funktionen. Da kann dir Google wirklich nicht weiterhelfen.
Wenn ich nach key_no aus Peters Code google, finde ich auch nichts
passendes ;-)
Funktionen sind es in der Tat nicht, sondern:
Converter ist ein Klassen-Template
Generator ist eine Klasse, geschrieben als Funktor
RightOpen, LeftOpen, ... Adjacent, ... sind Klassen gebraucht aus sog.
Tag-Typen.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Warum nicht C++17? Dann sind lambdas (automatisch) constexpr. Da geht>> das alles viel einfacher.> Naja, die Idee war ja schon die Funktion genLUT wiederverwendbar zu> machen... :) Und das ging in C++14 halt auch. Keil und Konsorten können> auch kein C++17...
Au weia, schlafen die alle?
> Wilhelm M. schrieb:>> Allerdings haben wir damit nur die Tabelle,> Peter's Funktion ließe sich damit direkt problemlos nutzen. Wollte sie> nur nicht kopieren.
Na ja, sollt eman umbauen, damit das Sentinel 0 nicht stört.
> Wilhelm M. schrieb:>> Macht man dieses Beispiel etwa auch noch auf einem AVR, so landet die>> Tabelle im RAM, entweder im data-segment oder auf dem Stack (als local>> object). Deswegen habe ich oben mit einem PgmArray gearbeitet.> Ja, sowas braucht man da auch, aber ich kenn mich mit der ganzen> AVR-Progmem-Geschichte nicht so aus, bin zu verwöhnt von ARM :)
Ich wollte es nur erwähnen, sonst gibt es gleich wieder großes Geschrei
... und wie gesagt, auch dafür gibt es eine Lösung.
Wilhelm M. schrieb:> Au weia, schlafen die alle?
Die entwickeln halt lieber "wichtige" Dinge weiter wie die
Klicki-Bunti-GUI. Im Embedded Bereich ist C++ ja eh verteufelt. Da bin
ich froh dass sie es bis C++14 geschafft haben... Selbst MSVC kann C++17
noch nicht.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Au weia, schlafen die alle?>> Die entwickeln halt lieber "wichtige" Dinge weiter wie die> Klicki-Bunti-GUI. Im Embedded Bereich ist C++ ja eh verteufelt. Da bin> ich froh dass sie es bis C++14 geschafft haben... Selbst MSVC kann C++17> noch nicht.
Hier sieht es aber bzgl. MSCV ganz gut aus:
https://en.cppreference.com/w/cpp/compiler_support
Keil könnte sich ja das frontend von EDG kaufen - das machen einige auch
für ihre IDEs.
Bei allem Respekt vor euren c++ Kenntnissen, auf die ich schon ein
bisschen neidisch bin: was nützt es, geilen Code zu schreiben, der nur
von 10% der potentiellen Kollegen verstanden wird? Ich benutze auch
gerne einen Teil von c++, aber da ich ab und zu ein Produkt ausliefern,
weiter entwickeln oder gar warten muss, habe ich leider nicht in dem
Maße Zeit mich in neue c++e einzuarbeiten. Ich verstehe leider
vornehmlich Bahnhof.
Wilhelm M. schrieb:> Hier sieht es aber bzgl. MSCV ganz gut aus:
Aha, das ist ganz neu - jetzt auch mit fold expressions und
template-auto. Gut zu wissen, dann kann ich meinen C++17 Code damit mal
testen.
Hier steht mehr dazu:
https://blogs.msdn.microsoft.com/vcblog/2018/05/07/announcing-msvc-conforms-to-the-c-standard/Karl schrieb:> was nützt es, geilen Code zu schreiben, der nur> von 10% der potentiellen Kollegen verstanden wird?
Es gibt Kollegen die können C++. Das gleiche Problem hat man doch mit
allen Tools und Sprachen - von Assembler bis Prolog. Das ist kein
prinzipielles Problem von C++. Bei meinem AG ist C++ die Hauptsprache,
neben einer ganzen Reihe weiterer.
Wilhelm M. schrieb:> u = o = 0;> if (output_mv < 400) u = (o = (output_mv / 100) * 2 + 2) + 1;
warum nicht gleich als einzeiler!?
if (u = o = 0, output_mv < 400) u = (o = (output_mv / 100) * 2 + 2) + 1;
Mark W. schrieb:> if(output_mV > 199 && output_mV < 300)> {> o = 8;> u = 9;> }>> if(output_mV > 299 && output_mV < 400)> {> o = 10;> u = 11;> }
so etwas würde ich immer "verdichten", ich hasse dieses sinnlose
klammern von "einzeiler" und auch die bedingung sinniger hinschreiben.
if (200 <= output_mV && output_mV < 300) o = 8, u = 9;
else if (300 <= output_mV && output_mV < 400) o = 10, u = 11;
mt
Karl schrieb:> was nützt es, geilen Code zu schreiben, der nur> von 10% der potentiellen Kollegen verstanden wird?
Zumal die 30 Originalzeilen (bei Blocksatz) gut lesbar sind.
Das C++ laufzeittechnisch super effektiv ist, für solche Dinge besser
als jede andere Sprache, geschenkt.
Bei solchen Beispielen wird klar, warum Funktion mit mehr als 10 Zeilen
böse sind und Unittests unverzichtbar.
Dr. Sommer schrieb:> Es gibt Kollegen die können C++.
Ja. Aber Wilhelm meint offenbar, man könnte auch als "normaler"
C-Programmierer ratzfatz auf C++ umsteigen. Dabei versucht er, mit
Tonnen von sehr fortgeschrittenem (aber leider auch unvollständigen und
damit oft nicht compilierbaren) C++17-Code sogar C-Anfänger für C++
umzustimmen.
Dass er mit seinen Beispielen, die eher wie Kanonen auf Spatzen wirken,
einen potentiellen C-nach-C++-Umsteiger eher abschreckt, scheint er
absolut zu ignorieren.
Peter (peda), der bekanntermaßen schon seit Jahren viele gute
C-Programme hier im Forum vorstellt und damit auch als C-Experte hier
bekannt ist, hat ja oben geschrieben, dass er bei Wilhelms Code nur noch
Bahnhof versteht. Dabei hat er vorher guten Willen gezeigt, Wilhelms
Code auch zu verstehen und auch nachzuvollziehen.
Wilhelm ignoriert das einfach und versucht gar nicht erst, Peters
Bedenken und Zweifel durch entsprechende Erklärungen und Hilfestellungen
zu zerstreuen - ganz im Gegenteil: Er ignoriert einfach Peters Beiträge,
um stattdessen auf Dr. Sommers Variante eine noch komplexere
C++-17-Version oben draufzulegen.
@Wilhelm: Warum gehst Du auf Peters Verständnisprobleme erst gar nicht
ein? Der einzige Eindruck, den Du damit hinterlässt: Du kaperst
C-Anfänger-Probleme-Threads, um dann C++ den Leuten madig zu machen,
indem Du möglichst komplexe Beispiele postest.
Warum zäumst Du das Pferd von hinten auf, statt in mehreren Schritten
vom einfachen Beispiel letztendlich zur eleganten Variante zu kommen?
Dann könnte man Deine Gedankengänge wenigstens nachvollziehen.
Voraussetzung ist natürlich:
- Angabe des Compilers
- Angabe der C++-Version (also bei Dir 17)
- Vollständig compilierbarer Code
Um möglichst viele Leute zu erreichen, wäre es auch nicht gerade dumm,
bei der C++-Version eher Abstriche zu machen und auch mal zu C++14 (oder
älter) zurückzugehen, wie es Dr. Sommer gemacht hat. Nicht jeder hat den
neuesten GCC auf seinem Rechner.
Aber so, wie Du das machst, wird das nichts. Solange Du einfach die
Leute ignorierst, die ihre Verständnisprobleme äußern und damit auch
Hilfestellungen Deinerseits erwarten, machst Du denen C++ nicht gerade
schmackhaft. Leider erreichst Du mit Deiner "Mission" das Gegenteil,
welches Du vermeintlich zu erreichen suchst.
Karl schrieb:> Bei allem Respekt vor euren c++ Kenntnissen, auf die ich schon ein> bisschen neidisch bin: was nützt es, geilen Code zu schreiben, der nur> von 10% der potentiellen Kollegen verstanden wird? Ich benutze auch> gerne einen Teil von c++, aber da ich ab und zu ein Produkt ausliefern,> weiter entwickeln oder gar warten muss, habe ich leider nicht in dem> Maße Zeit mich in neue c++e einzuarbeiten. Ich verstehe leider> vornehmlich Bahnhof.
Das erinnert an die viel zitierte Geschichte vom Förster und Holzfäller
...
Eine sehr einfaches, gut machbares, für jeden erreichbares und in jeder
Firma durchführbares Hilfsmittel sind das, was man früher "Standups"
nannte, die hier mal als Dailies bezeichnet werden:
https://www.fluentcpp.com/2017/04/04/the-dailies-a-new-way-to-learn-at-work
Frank,
ich hatte heute zweimal geschrieben, daß es bei Wilhelms Code normal
ist, wenn er aus einfachen Sachen Code macht, der in keiner Weise mehr
nachvollziehbar ist. Schließlich ist das jetzt in mehreren Threads schon
so gewesen. Und daß so eine Praxis reiner Wegwerfcode ist, weil
spätestens der Maintenanceprogrammierer danach das nicht mehr
durchdringen wird.
Beidemale hat einer Deiner Moderatorkollegen das kommentarlos gelöscht,
obwohl es genau darauf hinausläuft, was Du jetzt selber als Moderator
schreibst. Wieso?
Frank M. schrieb:> Peter (peda), der bekanntermaßen schon seit Jahren viele gute> C-Programme hier im Forum vorstellt und damit auch als C-Experte hier> bekannt ist, hat ja oben geschrieben, dass er bei Wilhelms Code nur noch> Bahnhof versteht.
Ja, das war sein Kommentar zum ersten Post von Dr. Sommer. Danach kam
allerdings keine konkrete Frage mehr.
> Wilhelm ignoriert das einfach und versucht gar nicht erst, Peters> Bedenken und Zweifel durch entsprechende Erklärungen und Hilfestellungen> zu zerstreuen - ganz im Gegenteil:
Fragen will auch gelernt sein.
> @Wilhelm: Warum gehst Du auf Peters Verständnisprobleme erst gar nicht> ein?
Dazu sollte er mal eine konkrete Frage stellen. Bahnhof reicht nicht.
Wer keine konkrete Frage stellen kann, hat sich nicht damit
auseinandergesetzt.
> Voraussetzung ist natürlich:>> - Angabe des Compilers> - Angabe der C++-Version (also bei Dir 17)> - Vollständig compilierbarer Code
Malen nach Zahlen führt kaum zu einem Erkenntnisgewinn (und wird hier in
dem Forum ja gerne als Arduino-like bezeichnet). Man liest sich den Code
durch und stößt auf etwas unbekanntes. Dann schaut man selbständig mal
nach was das sein könnte und konstruiert in seinem Umfeld mit seinen
Bezeichnern, etc. ein eigenes Beispiel. Wenn das nicht funktioniert,
dann kann nachfragen. Aber man muss schon eine Frage haben.
> Um möglichst viele Leute zu erreichen, wäre es auch nicht gerade dumm,> bei der C++-Version eher Abstriche zu machen und auch mal zu C++14 (oder> älter) zurückzugehen, wie es Dr. Sommer gemacht hat. Nicht jeder hat den> neuesten GCC auf seinem Rechner.
Im Interesse der Weiterbildung könnte man aber mal einen neueren dazu
installieren. Richtet ja keinen Schaden an.
> Aber so, wie Du das machst, wird das nichts. Solange Du einfach die> Leute ignorierst, die ihre Verständnisprobleme äußern und damit auch> Hilfestellungen Deinerseits erwarten, machst Du denen C++ nicht gerade> schmackhaft. Leider erreichst Du mit Deiner "Mission" das Gegenteil,> welches Du vermeintlich zu erreichen suchst.
Ich bin nicht angetreten, um zu missionieren. Wer das nicht interessant
findet, soll es halt ignorieren. Die anderen können ja fragen. Aber das
setzt natürlich voraus, dass man sich ausreichend mit den Dingen
beschäftigt. Anschauen, zurücklehnen, erkennen, das man nichts versteht,
Bahnhof sagen, und dann darauf warten, das es mundgerecht zerteilt wird:
nein, so läuft das nicht. Das ist eine Anspruchshaltung, die auch im
echten Leben nicht zum Erfolg führt.
Nop schrieb:> Beidemale hat einer Deiner Moderatorkollegen das kommentarlos gelöscht,> obwohl es genau darauf hinausläuft, was Du jetzt selber als Moderator> schreibst. Wieso?
Weil du eine bloße Anschuldigung hingeworfen hast, ohne irgendeine
Argumentation, pure Behauptung. (Unsinnige Behauptungen wie die über
den vorgeblichen „Maintenanceprogrammierer“ hast du dir ja selbst
diesmal nicht verkneifen können.)
Wenn du den riesigen Unterschied zwischen deinem „Beitrag“ und Yalus
recht ausführlicher und im Gegensatz zu dir durchaus sachlicher
Argumentation nicht siehst, sorry.
Merke: sowie in deinem Satz das Wort „immer“ als Beschreibung von
Verhaltensweisen eines anderen auftaucht, ist dieser eigentlich von
vornherein eine falsche Aussage, deren offenbar einziger Zweck dann
Polemik ist.
Jetzt lies dir bitte Yalus Argumentation nochmal durch.
Jörg W. schrieb:> Weil du eine bloße Anschuldigung hingeworfen hast, ohne irgendeine> Argumentation, pure Behauptung.
Mit anderen Worten, Du hast die Vorgeschichte in den anderen Threads
nicht mitbekommen. Kann passieren, aber das hättest Du nachfragen
können, statt einfach zu löschen. Abgesehen davon ist Franks Beitrag
ebenfalls Behauptung, denn er verlinkt auch nicht auf die relevanten
Threads im Sinne eines Quellennachweises.
Ich kann Dir ziemlich genau sagen, was der Unterschied ist: Frank ist
auch Moderator und ich nicht.
> (Unsinnige Behauptungen wie die über> den vorgeblichen „Maintenanceprogrammierer“ hast du dir ja selbst> diesmal nicht verkneifen können.)
Das ist keine unsinnige Behauptung, sondern Realität in der Industrie.
Wenn Du solche Projekte noch nicht erlebt hast, sei froh, aber
klassifizier es nicht als Unsinn. Die Anführungszeichen deuten darauf
hin, daß Du nicht einmal weißt, worum es geht.
Der Grundplot ist der, daß C++ zu komplex ist, als daß man ALLES
verstehen könnte. Wenn man nun wahllos 10 Programmierer hat, die alle
ihre 30% Verständnis mischen, dann muß der Maintenanceprogrammierer die
Obermenge von all dem können muß UND darin auch noch die Bugs finden
muß, die erst später auftreten.
Deswegen wird üblicherweise nur ein kleines Subset von C++ verwendet.
Selbst bei C wird das so gemacht, deswegen gibt es ja MISRA-C.
Wilhelm M. schrieb:> Das erinnert an die viel zitierte Geschichte vom Förster und Holzfäller> ...
Meinst du die?
https://www.motivate-yourself.de/geschichte-holzfaeller-waldarbeiter-saege-stumpf/
Da würde ich direkt widersprechen. Es geht nicht nur darum, zu wenig
Zeit zum Lernen zu haben, sondern diesen Zeitaufwand gegen die evtl
nötige mehrarbeit ohne das gelernte und den langfristigen wert des codes
abzuwägen.
Wenn alle Teilnehmer am Thread in einer Abteilung wären, könnte nur dr.
Sommer deinen Code verwenden. Toll.
Offtopic: Dein Auftreten finde ich unangenehm und ein bisschen
überheblich. Du scheinst zeigen zu wollen, wie gut du c++ beherrschst.
Das ist gelungen.
Die gezeigten C++ Beispiele sehen ja alle recht tolle aus. Aber es kommt
mir doch für die kleineren Sachen als etwas Overkill vor.
Wenn ichs mir richtig überlege, liebe ich Pedas Forum Codebeispiele. Die
sind immer pure Essenz. Oft am Anfang schwer zu verstehen, dann als
brilliant verstanden. Auch sind sie immer sehr Platz orientiert und
passen gut auf kleine uC. Als Vorbild finde ich daher seinen
Programmierstil und Ansatz sympatischer.
Das soll jetzt keine Kritik an C++ sein. Aber die Welt sollte groß genug
sein, damit jedes Tierchen sein Pläsierchen finden kann. Nicht jeder der
hier im Forum mitmacht ist ein SW Guru der damit seine Brötchen verdient
und damit auch im Schlaf sicher wandelt. Wenn doch vielmehr ein breites
Spektrum an Können in beiden Richtungen vorhanden ist.
Wenn man sich erinnert, daß C als ASM Ersatz in die Welt gerufen wurde,
müßte man eigentlich zugeben, daß C dann schon ein wahrer Luxus ist,
auch wenn man im neuesten C++ komplizierte Konstrukte einfacher in Code
kleiden kann und mächtige Möglichkeiten hat. Naja, wer's kann und sich
damit wohlfühlt und die Firma erwartet, daß man es kann, dann ist ja
alles gut.
Deshalb plädiere ich, C trotzdem noch nicht ganz abzuschreiben. Viele
Projekte können damit auch heutzutage noch bequem durchgezogen werden.
Und wem C in Fleisch und Blut übergegangen ist, der wird oft mit
esoterischen C++ sowieso lange keine Freude haben. Der Weg scheint
zumindest mir als sehr steinig zu sein.
Mfg,
Ein Heimlehrgangsprogrammierer
Nop schrieb:>> Weil du eine bloße Anschuldigung hingeworfen hast, ohne irgendeine>> Argumentation, pure Behauptung.>> Mit anderen Worten, Du hast die Vorgeschichte in den anderen Threads> nicht mitbekommen.
Die ist mir egal. Hier geht es um dein Auftreten in diesem
Thread. Das fiel für mich unter „vorsätzliche Störung des
Forenbetriebs“ (also: Trollbeitrag), da du eben einfach nur eine
bloße Behauptung provokativ hingeworfen hast.
> Kann passieren, aber das hättest Du nachfragen> können, statt einfach zu löschen.
Wie soll ich bitteschön bei dir nachfragen, wenn du keine Mailadresse
angeben magst?
Sorry. Genau dafür darf man auch bei anonymen Postings eine
Mailadresse hinterlegen: damit wir ggf. mal rückfragen können (jemand
anders sieht sie ja sowieso nicht). Wenn jemand auf diese Möglichkeit
verzichtet, dann gehe ich davon aus, dass er an Rückfragen nicht
interessiert ist.
Solchen Käse wie den jetzt hier gerade im Thread breitzutreten, ist
für das Forum einfach nur lästig und auch vom Betreiber ausdrücklich
unerwünscht.
> Abgesehen davon ist Franks Beitrag> ebenfalls Behauptung, denn er verlinkt auch nicht auf die relevanten> Threads im Sinne eines Quellennachweises.
Franks (sorry, mit Yalu verwechselt, der war weiter oben aktiv) Beitrag
ist Argumentation, nicht nur eine hingeschmissene Behauptung.
Nochmal: wenn du den himmelweiten Unterschied zwischen deinem und
seinem Beitrag nicht siehst, dann tut es mir leid, aber dann wundere
dich nicht, wenn wir sowas ggf. auch mal als linienüberschreitend
empfinden und rauswerfen.
> Ich kann Dir ziemlich genau sagen, was der Unterschied ist: Frank ist> auch Moderator und ich nicht.
Andersrum wird der Schuh draus: weil Frank eben bereits seit Jahren
mit einem guten Diskussionsstil aufgefallen ist, ist er Moderator
geworden.
>> (Unsinnige Behauptungen wie die über>> den vorgeblichen „Maintenanceprogrammierer“ hast du dir ja selbst>> diesmal nicht verkneifen können.)>> Das ist keine unsinnige Behauptung, sondern Realität in der Industrie.
Es ist alles mögliche Realität in der Industrie.
Das allein macht es nicht verallgemeinerungswürdig. (Btw., auch ich
bin „in der Industrie“ tätig, ich weiß also auch, wovon wir reden.)
> Der Grundplot ist der, daß C++ zu komplex ist, als daß man ALLES> verstehen könnte.
Das bestreitet gewiss keiner.
Anderen Sprachen geht das genauso.
Ich habe übrigens absolut nicht bestritten, dass ich Wilhelms
Programmbeispiele in der präsentierten Form nicht lehrreich finde;
wenn man sowas schon als Beispiel für andere hinschreiben will, dann
muss man es zumindest tiefergehend erläutern und/oder Kommentare
einfügen.
Es ging hier aber nicht um Inhalte, sondern die (also deine) Form
der Kritik. Es ist eben ein großer Unterschied, ob man eine Kritik
sachlich rüberbringen kann, oder Worte wie „immer“ und „schreibt
gern write-only Code“ dafür benutzt.
> Deswegen wird üblicherweise nur ein kleines Subset von C++ verwendet.
Welches sich natürlich je nach Organisation unterscheiden kann.
> Selbst bei C wird das so gemacht, deswegen gibt es ja MISRA-C.
MISRA ist erstens nicht der Nabel der Industrie (sondern nur eines
Teils der Industrie), zweitens ja durchaus auch zumindest in Teilen
umstritten.
Jörg W. schrieb:> Wie soll ich bitteschön bei dir nachfragen, wenn du keine Mailadresse> angeben magst?
So, wie Du es jetzt gerade auch tust. Im Übrigen bin ich nicht der
Einzige, dem es negativ auffällt, wenn Wilhelm öfter Threads mit
C++-Gespamme kapert. Das passiert jetzt nicht zum erstenmal, so daß es
mich schon überrascht, wenn Du davon noch gar nichts mitbekommen hast.
> Das allein macht es nicht verallgemeinerungswürdig. (Btw., auch ich> bin „in der Industrie“ tätig, ich weiß also auch, wovon wir reden.)
Maintenanceprogrammierer sind in der Industrie völlig normal. Mag sein,
daß der Begriff auf deutsch nicht üblich ist, aber da ich mehr englisch
als deutsch lese, fiel mir für "maintenance programmer" halt keine
bessere Übersetzung ein.
Ist doch auch logisch. Während der aktiven Entwicklung braucht man eben
deutlich mehr Entwickler. Irgendwann ist das Projekt aber fertig, dann
geht es um Pflege, Bugfixes und Erweiterungen. Dafür stellt aber keine
Firma mehr die volle Mannschaft hin, sondern das wird runtergefahren.
Zudem nimmt man dafür typischerweise auch eher die neu eingestellten
Leute.
> Es ging hier aber nicht um Inhalte, sondern die (also deine) Form> der Kritik. Es ist eben ein großer Unterschied, ob man eine Kritik> sachlich rüberbringen kann, oder Worte wie „immer“ und „schreibt> gern write-only Code“ dafür benutzt.
Wie gesagt, daß liegt daran, daß Wilhelm das in diesem Stil mit einiger
Regelmäßigkeit tut, und nach demselben Muster. Lies Dir die Reaktionen
doch durch hier. Wenn jemand versucht, über das Disassembly
rauszukriegen, was der Code eigentlich tut, ist das geradezu die
Definition von write-only-Code.
Ich mag mir gar nicht ausmalen, was für Code dabei wohl rauskäme, wenn
der auch noch inhaltlich anspruchsvolle Funktionen erfüllen sollte.
Und nein, das liegt nicht zwingend an C++ an sich, sondern es zieht
solche Leute nur verstärkt an. Der Code von Stockfish etwa, einer der
stärksten Schach-Engines der Welt, ist auch in C++ und sieht trotzdem
nicht so aus.
Nop schrieb:> Ich mag mir gar nicht ausmalen, was für Code dabei wohl rauskäme, wenn> der auch noch inhaltlich anspruchsvolle Funktionen erfüllen sollte.
Schon mal daran gedacht, daß sich manche Vorteile von mehr Abstraktion
bei "Blinky"-Äquivalent-Code noch nicht auswirken?
> Und nein, das liegt nicht zwingend an C++ an sich, sondern es zieht> solche Leute nur verstärkt an. Der Code von Stockfish etwa, einer der> stärksten Schach-Engines der Welt, ist auch in C++ und sieht trotzdem> nicht so aus.
Was ein Wunder für ein Stück Code, das 13 Jahre bevor C++17
verabschiedet wurde, entstand. Immerhin haben sie vereinzelt constexpr
nachgelegt. Das grundsätzliche Design basiert aber auf C++03.
Warum haben die das eigentlich noch nicht nach Rust portiert, das ist
doch viel hipper?
Weia, was für eine Beitrags-Flut...
Irgendwie nervt mich dieses Standard-Totschlag-Argument "die Kollegen
müssen das auch verstehen". Wenn man danach geht bleibt man ewig bei
C90, RCS und 8051 stecken. Das ist wie die sagenumwobene Glass Ceiling,
man kann sich nicht weiter entwickeln und bleibt immer auf dem selben
Stand. Irgendwann will man auch einfach mal was neues probieren und
nicht den 10000. String-Verarbeitungs-Algorithmus in C manuell schreiben
weil es in C nicht anders geht... Und es kann ja auch nicht sein dass
der einzige Weg dafür darin besteht zum PowerPoint-Entwickler zu werden.
Höhere Programmiersprachen wurden ja auch nicht zum Spaß erfunden, C ist
längst nicht mehr das Maß aller Dinge, da steckt auch viel Potential zur
Effizienz-Steigerung drin.
Wenn man hier im Forum ein C++ Beispiel zeigt will man zeigen wie es
auch geht ohne jetzt bei Adam und Eva anfangen und alles erläutern zu
wollen. Dazu gibt es Bücher und Tutorials. Blöd ist nur wenn es eher
abschreckend wirkt...
Heimlehrgangsprogrammierer schrieb:> Deshalb plädiere ich, C trotzdem noch nicht ganz abzuschreiben.
Oh, das passiert auch nicht. C ist halt viel Handarbeit, was immer dort
gut ist, wo die vielen hilfreichen aber komplizierten Schablonen anderer
Sprachkonzepte nicht so ganz passen.
Dr. Sommer schrieb:> C ist> längst nicht mehr das Maß aller Dinge,
wie wahr! beispiel, ich portiere gerade einige meiner quellen nach
micopython und bin beeindruckt von python auf "kleiner" hardware ...
mt
Frank M. schrieb:> Peter (peda), der bekanntermaßen schon seit Jahren viele gute> C-Programme hier im Forum vorstellt und damit auch als C-Experte hier> bekannt ist,
Bei allem Respekt, PeDa ist auch einer derjenigen, dessen Code schonmal
unleserlich geschrieben ist, um Zeilen oder auch Zeichen zu sparen.
Selbsterklärenden Code schreibt der auch nicht immer.
Und natülich treffen mit Peda als HardCore-K&R-C'ler und Wilhelm als
HardCore C++20'ler völlig verschiedene Welten aufeinander ;)
Oliver
Carl D. schrieb:> Schon mal daran gedacht, daß sich manche Vorteile von mehr Abstraktion> bei "Blinky"-Äquivalent-Code noch nicht auswirken?
Sagte ich ja, das wird noch schlimmer, wenn dahinter auch noch Funktion
steht. Genau das meinte ein gewisser Torvalds, als er bei Git nicht nur
kein C++ wollte, sondern auch C++-Programmierer draußenhalten. Obwohl
Git ja nun eindeutig nicht Kernel ist.
Dr. Sommer schrieb:> Irgendwie nervt mich dieses Standard-Totschlag-Argument "die Kollegen> müssen das auch verstehen".
Es ist halt nicht nur das reine Programmieren, sondern auch noch
Domänenwissen, was ebenfalls Jahre braucht. Zuguterletzt will sich auch
nicht jeder nach einem realen Arbeitstag auch noch in der Freizeit damit
endlos beschäftigen müssen. C hat den grundlegenden Vorteil, den C++
längst verloren hat - es ist eine kompakte Sprache, die man nicht nur in
der Breite, sondern auch in der Tiefe noch gut überschauen kann.
Aber in der realen Industrie mit Bezug zu embedded ist ja schon C zu
tricky, daher MISRA-C. Zumal dort auch erheblichenteils nicht
Informatiker tätig sind, aus guten Gründen.
Oliver S. schrieb:> Bei allem Respekt, PeDa ist auch einer derjenigen, dessen Code schonmal> unleserlich geschrieben ist, um Zeilen oder auch Zeichen zu sparen
Ich denke, das liegt vielmehr daran, dass PeDa in einer Zeit mit C
groß geworden ist, als sein 8051-Compiler noch viel blöder als der
Programmierer war. Damit hat der Programmierer dann „voroptimiert“.
Mit heutigen Compilern auf heutiger Hardware braucht man sowas nicht
mehr, da kann man eigentlich immer leserlichen Code schreiben.
Die Überschrift des TE war ja auch reichlich unglücklich gewählt: es
kam ihm ja gar nicht darauf an, den Code unleserlich zu machen,
sondern er meinte damit „unorthodox geschrieben“, letztlich aber, um
eine Verbesserung der Lesbarkeit zu erreichen.
Dr. Sommer schrieb:> Wenn man hier im Forum ein C++ Beispiel zeigt will man zeigen wie es> auch geht ohne jetzt bei Adam und Eva anfangen
Das verlangt ja auch keiner.
Nur sollten die Beispiele auch wenigstens compilierbar sein.
Und dazu gehört nunmal, daß man die minimal nötige Compilerversion
angibt, sowie auch alle benötigten privaten Header postet oder verlinkt.
Peter D. schrieb:> Dr. Sommer schrieb:>> Wenn man hier im Forum ein C++ Beispiel zeigt will man zeigen wie es>> auch geht ohne jetzt bei Adam und Eva anfangen>> Das verlangt ja auch keiner.> Nur sollten die Beispiele auch wenigstens compilierbar sein.> Und dazu gehört nunmal, daß man die minimal nötige Compilerversion> angibt, sowie auch alle benötigten privaten Header postet oder verlinkt.
Es ergeben sich hier zwei Probleme:
1) Target AVR: es existiert aber keine libstc++ für diese Target. Da
wird jeder seine eigene haben, oder manche benutzen auch
https://www.etlcpp.com (die ich selbst nicht verwende, da ich in meiner
Variante noch Optimierungen vorgenommen habe, manche Teile darf ich
nicht veröffentlichen, leider kein OSS)
2) In dem oben geposteten Beispiel tauchen Meta-Funktionen aus einer
(meiner) TMP-Bibliothek auf. Diese kann/darf ich leider nicht öffentlich
zur Verfügung stellen, auch leider kein OSS.
In Deinem Fall Peter gehe ich davon aus, dass Du als Target AVR hast.
Hier musst Du also erst mal Problem 1) lösen.
Wenn Du das geschafft hast, bleibt Problem 2). Der Code wird an ein paar
wenigen Stellen nicht compilieren. Hier kann ich gerne helfen, ohne dass
ich die ganze TMP-Bibliothek zur Verfügung stellen muss. Dies wäre auch
gleichzeitig ein guter Einstieg in TMP.
Wobei ich der Meinung bin, dass die Funktion von
1
usingx=Meta::pop_front<list>;
klar sein sollte. Wenn man die libstdc++ kennt, hat man mindestens mal
eine Vermutung, was das macht. Wenn das nicht der Fall ist, musst Du
Dich zunächst einmal mit TMP beschäftigen. Ansonsten ist der Lerneffekt
wieder null.
Bottom line: zuerst Problem 1 lösen unabhängig von den hier gezeigten
Beispielen (oder anderes Target wählen), dann Problem 2 angehen mit
Wissen über TMP.
Wilhelm M. schrieb:> Diese kann/darf ich leider nicht öffentlich zur Verfügung stellen, auch> leider kein OSS.
Dann veröffentliche doch bitte auch keine Beispiele, die darauf
aufsetzen, das hat doch sonst keinerlei Wert für die Community.
Wenn schon, dann liefere halt Rewrites für die entsprechenden Teile.
Dein Problem #1 kann man getrost erstmal zur Seite schieben, solange
sich der Kram dann wenigstens auf dem PC compilieren lässt, denn dann
lässt sich das Beispiel zumindest nachvollziehen. Selbst für Leute,
die primär sonst auf Controllern arbeiten, schadet es ja nicht, wenn
man irgendeine Demonstration zuerst einmal nur auf dem PC machen
kann. Ob und wann und unter welchen Umständen man sowas auf eine
Controllerplattform transferieren will, kann dann allemal jeder selbst
entscheiden.
Solange du aber Dinge postest, die ohnehin keiner nachvollziehen kann,
hinterlässt das eben eher den Beigeschmack von Angeberei als den, dass
du anderen Leuten „auf die Sprünge“ helfen möchtest.
Jörg W. schrieb:> Wilhelm M. schrieb:>> Diese kann/darf ich leider nicht öffentlich zur Verfügung stellen, auch>> leider kein OSS.>> Dann veröffentliche doch bitte auch keine Beispiele, die darauf> aufsetzen, das hat doch sonst keinerlei Wert für die Community.
Ok, dann lösche bitte alle meine vorigen Beiträge in diesem Thread!
>> Wenn schon, dann liefere halt Rewrites für die entsprechenden Teile.
Sonst noch Wünsche?
> Solange du aber Dinge postest, die ohnehin keiner nachvollziehen kann,> hinterlässt das eben eher den Beigeschmack von Angeberei als den, dass> du anderen Leuten „auf die Sprünge“ helfen möchtest.
Wer Fragen zu TMP hat, soll dann einfach einen neuen Thread aufmachen,
und ganz groß C++ oben drüber schreiben, damit keine auf die Idee kommt,
irgendwelchen C oder Basic Code dort zu posten (was mch persönlich nicht
stören würde).
So, und nun bitte löschen (bis auf diesen hier).
Wilhelm M. schrieb:>> Wenn schon, dann liefere halt Rewrites für die entsprechenden Teile.>> Sonst noch Wünsche?
Alternativ auf eine der 982 OSS-TMP-Libraries umschreiben wie Boost.Hana
...
Wilhelm M. schrieb:> Ich bin nicht angetreten, um zu missionieren. Wer das nicht interessant> findet, soll es halt ignorieren. Die anderen können ja fragen.
Du hattest ja seinerzeit den sehr interessanten und mitunter lehrreichen
Thread
Beitrag "Informationen zu C vs C++ / aka Futter für die Diskussion"
gestartet, der auch heute noch regelmäßig neue Beiträge erfährt.
Kannst Du Dir eventuell vorstellen, dass Du dort eine interessiertere
und kompetentere Leserschaft findest als in solchen Trivial-C-Frage
Threads wie
Beitrag "switch(Funktion()) möglich?"
oder
Beitrag "Code unleserlich schreiben um Zeilen zu sparen." ?
Hier kommt jemand mit einer sehr einfachen Frage zu C, die dem Leser
direkt offenbart, dass der TO in Sachen C wahrscheinlich nicht nur
ziemlicher Anfänger ist, sondern gern auch hilfreiche Tipps zu seiner
Frage von den erfahrenen C-Programmierern wünscht.
Ich kann mir in beiden Fällen leider überhaupt nicht vorstellen, dass
der jeweilige TO, der sowieso schon mit C seine liebe Müh hat, aufgrund
Deiner intellektuell sehr anspruchsvollen C++-17-Code-Snippets nun sagen
wird: "Wilhelm hat Recht! Ich schmeiße C hin, nehme C++-17 und all meine
Probleme sind gelöst! Alles total easy!"
Ich habe jedenfalls in beiden oben genannten Threads keinerlei Reaktion
der beiden TOs erkannt - ganz im Gegenteil: Als die Diskussion über die
C++-Alternativen anfing, haben sich die TOs flugs aus dem Thread
ausgeklinkt, einfach, weil es sie vermutlich intellektuell in diesem
Stadium ihres Programmierer-Daseins absolut überforderte.
Das Problem, was ich dann als Moderator sehe: Der Thread driftet
komplett ab. Das eigentliche Thema tritt dann in den Hintergrund.
Stattdessen wird der ursprüngliche Trivial-C-Thread mit höchst
anspruchsvollem C++-17-Code regelrecht geflutet. Diesen Eindruck kann
man jedenfalls als Leser, den das ursprüngliche C-Thema interessiert,
durchaus gewinnen. Dieses Vorgehen mag dann in dem einen oder anderen
Auge des Betrachters gar als Kaperung oder sogar als "Spam" angesehen
werden.
Deshalb möchte ich Dir folgenden Vorschlag für solche Fälle für die
Zukunft machen:
Wenn Du für ein Trivial-C-Problem eine elegante C++-17-Lösung siehst,
die durchaus erwähnenswert ist, verlinkst Du vom Trivial-C-Thread nach
Beitrag "Informationen zu C vs C++ / aka Futter für die Diskussion"
um dort Deine C++-17-Variante weiterzudiskutieren.
Wäre das ein annehmbarer Vorschlag? In meinen Augen schon, denn dann
würden solche emotionsgeladenen Reaktionen wie hier erst gar nicht
auftreten.
P.S.
Ich schreibe oben mit Absicht nicht C++, sondern C++-17, da die hier
geposteten Code-Snippets allesamt inkompatibel zu älteren bzw. zu den
meisten auf dem Markt eingeführten C++-Versionen sind.
Wilhelm M. schrieb:> Ansonsten ist der Lerneffekt wieder null.
Ich finde den Anspruch, das andere vorab was lernen sollen, nicht
gerechtfertigt. Man sollte doch erst mal sehen, dass ein Problem
eleganter gelöst ist. Wenn es hingegen komplexer und objektiv schwerer
lesbar ist, ... wieso dann noch eintauchen? Zumal C++ hier ja meist der
Optimierung (Speicher und Laufzeit) dient.
Wenn Standard-C++ Standardschablonen für ein Problem hat: Super.
Aber das Argument, dass Du eigene Schablonen für ein Problem hast oder
erstellen kannst, ... Ich las hier einige Threads (ohne Autoren oder
Sprachen zu erinnern), wo ein überschaubares Problem "vereinfacht"
wurde, indem es hinter einer Funktion versteckt wurde, deren
Implementierung dann dem Leser überlassen hat :-)
Wilhelm M. schrieb:> 2) In dem oben geposteten Beispiel tauchen Meta-Funktionen aus einer> (meiner) TMP-Bibliothek auf. Diese kann/darf ich leider nicht öffentlich> zur Verfügung stellen, auch leider kein OSS.
Es wäre schön gewesen, wenn das gleich über den Beispielen gestanden
hätte.
Gerade einem Anfänger fällt es schwer, zu erkennen, was ist aus
Standardlibs des Compilers und was nicht.
Frank M. schrieb:> Deshalb möchte ich Dir folgenden Vorschlag für solche Fälle für die> Zukunft machen:>> Wenn Du für ein Trivial-C-Problem eine elegante C++-17-Lösung siehst,> die durchaus erwähnenswert ist, verlinkst Du vom Trivial-C-Thread nach>> Beitrag "Informationen zu C vs C++ / aka Futter für die Diskussion">> um dort Deine C++-17-Variante weiterzudiskutieren.
Die Idee, Frank, wird so aber nicht zünden, denn in diesen Thread
schauen die C Programmierer nicht hinein. Eigentlich war es mein Wunsch,
in dem o.g. Thread auch nur Verweise auf andere (bessere) Quellen zu
verlinken. Dort erwähne ich ja auch des öfteren, dass die eigentlichen
Diskussion besser in anderen, leichter sichtbaren Thread geführt werden
sollten.
> Wäre das ein annehmbarer Vorschlag? In meinen Augen schon, denn dann> würden solche emotionsgeladenen Reaktionen wie hier erst gar nicht> auftreten.
Aber Frank, ich finde es sehr gut, dass Du Dir wirkliche, konstruktive
Gedanken machst!
Ich stehe zu meiner Grundaussage: "Stop teaching C". Nicht wegen der
Sprache C im engeren Sinne, sondern weil der Blick für die
Grundprinzipien des Programmierens verloren geht. Das gilt übrigens auch
- und das ist die eigentliche Aussage des Spruchs - wenn man mit dem C
in C++ beginnt.
Wer nicht in größeren Dimensionen denkt, kann an trivialen Beispielen
den eigentlichen Wert der meisten Beispiele und Umsetzung in
C++(17/20/..) nicht erkennen.
Bitte nicht falsch verstehen, denn ich bin nicht emotionsgeladen an
dieser Stelle, aber ich werde in Zukunft immer nachfragen, ob auch
Interesse an einem Ansatz (in C++) besteht.
Ich möchte jetzt aber dennoch meinem Wunsch nochmals starken Nachdruck
verleihen, meine Beiträge in diesem Thread zu löschen. Ich weiß, dass
Euch das Nutzungsrecht gehört, aber ich bitte einfach darum.
Wilhelm M. schrieb:> Ich möchte jetzt aber dennoch meinem Wunsch nochmals starken Nachdruck> verleihen, meine Beiträge in diesem Thread zu löschen. Ich weiß, dass> Euch das Nutzungsrecht gehört, aber ich bitte einfach darum.
Vielleicht überlegst Du dir das ja nochmal, wenn Du auch andere Stimmen
hörst?
Ich persönlich habe überhaupt kein Problem mit diesem Thread. Im
Gegenteil, ich hab' ihn genossen.
Der TO hat schon sehr früh erschöpfend Auskuft bekommen. Wahrscheinlich
mehr als er eigentlich wissen wollte. So what? Ab da kann man sich
anderen Dingen widmen.
Auch wenn ich persönlich nicht alles gut und richtig finde, was an
"neuem" C++ so kommt, selbst hauptsächlich in C programmiere (und daran
in absehbarer Zeit wahrscheinlich auch nichts ändern werde), finde ich
doch alles, was man "dazulernen" kann, gut und richtig. Ich muss es ja
nicht verwenden, wenn ich (für mich) das Gefühl habe, das es nicht
passt. Wem's gar nicht passt, der muss es nicht mal lesen.
Wenn dieses (Diskussions-) Forum nur noch Beiträge toleriert, die 100%ig
auf die gestellte Frage eingehen, verliert es (für mich) gewaltig an
Wert. Meist entstehen die wirklich interessanten Fragen und Antworten
gerade erst aus der Diskussion.
"Rummäkler" mäkeln meiner Ansicht nach oft genug lediglich aus
verletzter Eitelkeit mit Neid ("der kann was, was ich nicht mal
verstehe, das muss also akademischer Mist sein").
Da solltest Du drüber stehen. Kompetenz klingt halt nun manchmal
arrogant ... ;)
Markus F. schrieb:> Wenn dieses (Diskussions-) Forum nur noch Beiträge toleriert, die 100%ig> auf die gestellte Frage eingehen, verliert es (für mich) gewaltig an> Wert. Meist entstehen die wirklich interessanten Fragen und Antworten> gerade erst aus der Diskussion.>> "Rummäkler" mäkeln meiner Ansicht nach oft genug lediglich aus> verletzter Eitelkeit mit Neid ("der kann was, was ich nicht mal> verstehe, das muss also akademischer Mist sein").>> Da solltest Du drüber stehen. Kompetenz klingt halt nun manchmal> arrogant ... ;)
da bin ich voll dabei!
ich lese alles zu c++ und archiviere sogar die beipiele, die ich heute
zugegebenerweise absolut nicht verstehe, aber irgendwann mal
nachvollziehen möchte.
was mich richtig stört, ist die nivellierung nach unten und nicht die
vereinzelten "leuchtenen blüten"! ich würde gerne sehen, dass das forum
einen einsteiger- UND "experten" -bereich schaft.
also hört bitte auf damit, das niveau immer weiter nach unten zu
drücken, z.b. mit der begründung das jeder es verstehen soll.
ich denke, dass der niveauverfall in der gesellschft gewünscht und
gefördert wird. aber ich wehre mich dagegen - soll heisen was/wer
schrott/doof ist wird auch so benannt und nicht immer nur schön reden.
mt
Wilhelm M. schrieb:> Die Idee, Frank, wird so aber nicht zünden, denn in diesen Thread> schauen die C Programmierer nicht hinein.
Richtig. Vielleicht wäre es auch eine Idee, C-Programmierern nicht
permanent mit C++ auf den Senkel zu gehen. Dieses Missionieren ist
einfach nur lästig.
> aber ich werde in Zukunft immer nachfragen, ob auch> Interesse an einem Ansatz (in C++) besteht.
Ich fände es schön, wenn Du das in C-Threads einfach seinläßt. Du
fändest es umgedreht auch störend, wenn Du über C++ reden willst und
dann C-Programmierer stattdessen darüber diskutieren, daß das
schlichtweg Obfuscation ist.
Frank M. schrieb:> Ich kann mir in beiden Fällen leider überhaupt nicht vorstellen, dass> der jeweilige TO, der sowieso schon mit C seine liebe Müh hat, aufgrund> Deiner intellektuell sehr anspruchsvollen C++-17-Code-Snippets nun sagen> wird: "Wilhelm hat Recht! Ich schmeiße C hin, nehme C++-17 und all meine> Probleme sind gelöst! Alles total easy!"
Eines habe ich übrigens durchaus daraus gelernt, nämlich was offenbar
der Hintergrund war, wieso Torvalds in seinem bekannten Rant zum Thema
"Git in C?" schrieb "even if the choice of C were to do nothing but
keep the C++ programmers out, that in itself would be a huge reason to
use C."
Nunja, einfach damit das Projekt eben nicht mit solchem Code endet wie
demonstriert.
Nop schrieb:> Ich fände es schön, wenn Du das in C-Threads einfach seinläßt. Du> fändest es umgedreht auch störend, wenn Du über C++ reden willst und> dann C-Programmierer stattdessen darüber diskutieren, daß das> schlichtweg Obfuscation ist.
Hier besteht ein logisches Problem:
Du willst die C++ Beiträge nicht sehen, deswegen sollen sie nicht
geschrieben werden. Andere Teilnehmer wollen die Beiträge aber lesen
(und zwar in genau dem Zusammenhang, in dem sie jetzt stehen).
Lösung:
Die Beiträge werden weiterhin geschrieben und DU (und alle die ebenfalls
nicht interessiert sind) ignorierst sie.
mh schrieb:> Lösung:> Die Beiträge werden weiterhin geschrieben und DU (und alle die ebenfalls> nicht interessiert sind) ignorierst sie.
Schön, dann kann man auch jeden Thread mit anderem peripher
interessantem Offtopic zumüllen. Kann man ja überlesen, oder?
Nop schrieb:> Schön, dann kann man auch jeden Thread mit anderem peripher> interessantem Offtopic zumüllen. Kann man ja überlesen, oder?
Ich sehe kein Problem wenn sich die Diskussion in eine andere Richtung
bewegt, wenn genügend Teilnehmer daran interessiert sind.
Und C++ Alternativen zu C Beispielen sind nun wirklich kein Offtopic in
einem Thread der sich "Code unleserlich schreiben um Zeilen zu sparen"
nennt.
mh schrieb:> Und C++ Alternativen zu C Beispielen sind nun wirklich kein Offtopic in> einem Thread der sich "Code unleserlich schreiben um Zeilen zu sparen"> nennt.
Wobei danach das „unleserlich“ vom TE korrigiert worden ist: es sollte
durchaus besser lesbar werden, so die Intention. Dahingehend ist
manches der C++-Beispiele durchaus nicht gerade on-topic :), auch wenn
es vielleicht mehr „Coolheitsfaktor“ hat oder halt auch Arbeit spart,
wenn sich am Algorithmus zur Generierung der Daten mal was ändert
(wofür man im Original hätte die komplette Tabelle händisch neu
tippen müssen).
Jörg W. schrieb:> wenn sich am Algorithmus zur Generierung der Daten mal was ändert
Sowas ist z.B. praktisch für CRC-Tabellen (mit welchen man den
CRC-Algorithmus stark beschleunigen kann); die kann man per
constexpr-Algorithmus generieren und so spart man sich endlose
Zahlenfolgen im Code. Wenn man einen Parameter zur Erzeugung ändern will
kann man das im Code schnell abändern und muss keine externen Tools
anwerfen. Leider gibt's ja Protokolle die so vermurkste
Nicht-Standard-CRC's nutzen die man nicht mit den CRC-Hardwareeinheiten
von Mikrocontrollern erzeugen kann, wie z.B. beim LTC6804.
Dr. Sommer schrieb:>> wenn sich am Algorithmus zur Generierung der Daten mal was ändert>> Sowas ist z.B. praktisch für CRC-Tabellen (mit welchen man den> CRC-Algorithmus stark beschleunigen kann)
Nur: gerade diese legt man in der Regel genau einmal an, danach
sollten sie sich nicht mehr ändern. :)
Jörg W. schrieb:> Nur: gerade diese legt man in der Regel genau einmal an, danach> sollten sie sich nicht mehr ändern. :)
Na, sobald man einen anderen Kommunikationspartner mit anderen
Sonderwünschen an die CRC hat muss man sie neu anlegen...
Jörg W. schrieb:> mh schrieb:>> Und C++ Alternativen zu C Beispielen sind nun wirklich kein Offtopic in>> einem Thread der sich "Code unleserlich schreiben um Zeilen zu sparen">> nennt.>> Wobei danach das „unleserlich“ vom TE korrigiert worden ist: es sollte> durchaus besser lesbar werden, so die Intention. Dahingehend ist> manches der C++-Beispiele durchaus nicht gerade on-topic :),
Nun ja, in einem Thread, wo das Topic erst x ist und anschließend !x,
ist es per se ein wenig schwierig, on-topic zu bleiben, nicht wahr?
Also mir ist das Beispiel Programm von Wilhelm "unheimlich". Wenn man da
nicht wirklich ein solide C++ Grundlage, Verständnis und
Erinnerungsvermögen an die Sprachelemente und Beziehungen hat, ist es
dem Uneingeweihten praktisch unmöglich das Programm funktionell im
Detail zu untersuchen. Beim alten C ist praktisch alles offen und man
kann ein Programm sehr gut analysieren. Beim obigen Beispiel ist alles
hinter den Regeln und Sprachen Design Details versteckt. Als C++
Anfänger tut man sich dann richtig schwer die pertinenten Daten Details
und Zusammenhänge zu verstehen und verfolgen. Die "Aha" Momente muss man
sich als Laie hier schwer erarbeiten und kommen leider nur recht selten.
Wer da professionell tagtäglich mit dem neuesten C++ arbeitet, womöglich
noch einige Universitätskurse abgelegt hat, für den ist das natürlich
alltäglich und in Fleisch und Blut übergegangen. Also seid geduldig mit
dem Rest der Welt der diesen tiefen Einblick in die neuen
Sprachentwicklungen nicht immer hat. Was Euch selbstverständlich ist,
ist für den Rest der Welt oft nur noch "Bahnhof".
OK. Und jetzt trampelt bitte nicht zu sehr auf mich herum. Ich fand
diese Erörterungen durchaus sehr interessant. Aber im Augenblick muss
ich einen sehr großen Bogen um die Materie machen:-)
Schönen Tag noch,
Gerhard
Markus F. schrieb:> Nun ja, in einem Thread, wo das Topic erst x ist und anschließend !x
War es ja nicht wirklich, und wer die Beiträge des TE aufmerksam
gelesen hatte, dem wurde das schnell klar.
Seine Überschrift war halt nur arg ungeschickt ausgedrückt.
Vielleicht noch zwei Sachen zu der ganzen Thematik und Aufregung hier:
In dem Beitrag
Beitrag "Re: Code unleserlich schreiben um Zeilen zu sparen."
hatte ich vollständigen und funktionierenden Code gepostet, mit einer
kleinen Ausnahme, die ich dort auch beschrieben hatte: und zwar
Util::sort() aus dem Include-File "util/algorithm.h". Dazu hatte ich
geschrieben, dass es ein constexpr Bubble-Sort sein dürfte.
Meine Schlußfolgerung daraus war / ist: es hat niemand, der sich hier
beschwert hat, jemals ausprobiert, den Code in einer C++17 Umgebung zu
kompilieren. Hätte das jemand versucht, dann wäre es ihm wie beschrieben
ausgefallen und er hätte es lediglich auskommentieren müssen. Den die
Eingangsdaten des Algorithmus waren bereits sortiert. Oder eben ein
Bubble programmieren. Hey Leute, das war doch machbar oder?
Zum anderen warte ich auch eine Antwort eines der hier mitlesenden /
mitpostenden Moderatoren zu meinem nachdrücklichen Wunsch, meine
Beiträge hier zu löschen. Da ist leider nichts erfolgt.
Wilhelm M. schrieb:> Meine Schlußfolgerung daraus war / ist: es hat niemand, der sich hier> beschwert hat, jemals ausprobiert, den Code in einer C++17 Umgebung zu> kompilieren. Hätte das jemand versucht, dann wäre es ihm wie beschrieben> ausgefallen und er hätte es lediglich auskommentieren müssen.
Ich habe mal nachgesehen welche GNU Version für Windows erhältlich ist
und wenn ich es nicht falsch interpretiert habe, ist V5.1 die neueste
Version die allerdings bis C++14 unterstützt. V8 mit C++17 scheint es im
Augenblick nur für Linux zu geben. Wie gesagt ich kenne mich mit den
erhältlichen Versionen nicht so aus. V4.92 ist die neueste Version die
ich im Betrieb habe.
https://sourceforge.net/projects/tdm-gcc/files/latest/download
Gibt es eine C++17 Windows Version und kann man sich eine Windows
kompatible C++17 installieren?
Wilhelm M. schrieb:> Zum anderen warte ich auch eine Antwort eines der hier mitlesenden /> mitpostenden Moderatoren zu meinem nachdrücklichen Wunsch, meine> Beiträge hier zu löschen.
Finde zumindest ich unpassend. Dann müsste man einen ziemlich großen
Teil der Diskussion, die sich rundherum entsponnen hat, löschen, denn
die hat losgelöst keinen Sinn. Deine Beiträge verstoßen ja auch nicht
gegen die Nutzungsbestimmungen, sie sind eben (m. E.) nur nicht so
hilfreich, wie sie sein könnten, wenn sie auch jeder compilieren
kann (ok, jeder, den es interessiert).
Gerhard O. schrieb:> Wilhelm M. schrieb:>> MinGW / CygWin hat gcc-8.1 (C++2a)>> Danke!
Bei Cygwin ist es doch nur 7.3, sorry! Aber das sollte auch reichen.
Ansonsten: VM / ArchLinux
Wilhelm M. schrieb:> Bei CygWilhelm M. schrieb:> Gerhard O. schrieb:>> Wilhelm M. schrieb:>>> MinGW / CygWin hat gcc-8.1 (C++2a)>>>> Danke!>> Bei Cygwin ist es doch nur 7.3, sorry! Aber das sollte auch reichen.>> Ansonsten: VM / ArchLinux
OK. Danke für die Berichtigung.
Markus F. schrieb:> "Rummäkler" mäkeln meiner Ansicht nach oft genug> lediglich aus verletzter Eitelkeit mit Neid ("der> kann was, was ich nicht mal verstehe, das muss> also akademischer Mist sein").
Die Unverständlichkeit vieler Computerthemen ist
meiner Erfahrung nach nicht ihrer tatsächlichen
Kompliziertheit geschuldet, sondern der Unfähigkeit
bzw. der Unlust der Missionare, sich allgemein-
verständlich auszudrücken.
Die Geschichte der Informatik ist die Geschichte
schlechter Begriffsbildungen und hirnrissiger
Erklärungen.
Wenn ich Potenzial hinter einem Konzept erkenne, bin
ich durchaus lernwillig. Ich bin aber nicht bereit,
als Initiationsritus unter Schmerzen irgend einen
Gehirnkrampf auswendig zu lernen, nur um dazuzugehören.
Nop schrieb:> Carl D. schrieb:>>> Schon mal daran gedacht, daß sich manche Vorteile von mehr Abstraktion>> bei "Blinky"-Äquivalent-Code noch nicht auswirken?>> Sagte ich ja, das wird noch schlimmer, wenn dahinter auch noch Funktion> steht.
Das Prinzip von unterschiedlichen fixen und variablen Kosten und der
Punkt (meist etwas oberhalb von trivial) an dem "wenig fix/viel
variabel" Dei Variante "viel fix/wenig variabel" kostenmäßig überholt,
sollte auch nicht-BWLern geläufig sein. Naja, vielleicht auch nicht,
wenn nicht mal mein einfacher Satz für jeden sinnbegreifend lesbar ist.
> Genau das meinte ein gewisser Torvalds, als er bei Git nicht nur> kein C++ wollte, sondern auch C++-Programmierer draußenhalten. Obwohl> Git ja nun eindeutig nicht Kernel ist.
Wenn es um Linux (und auch GIT) geht, mag man ihn für einen Gott halten,
er ist aber sicher nicht unfehlbar.
Jörg W. schrieb:> Dr. Sommer schrieb:>>> wenn sich am Algorithmus zur Generierung der Daten mal was ändert>>>> Sowas ist z.B. praktisch für CRC-Tabellen (mit welchen man den>> CRC-Algorithmus stark beschleunigen kann)>> Nur: gerade diese legt man in der Regel genau einmal an, danach> sollten sie sich nicht mehr ändern. :)
Wenn man aber den Rechenweg hinschreibt, dann ist man einen Level
weiter.
Es gibt z.B. 1Wire-Slave Implementierungen für AVR, da steht dann:
"wenn die ID geändert wird, bitte online via <link> den neuen CRC-Wert
berechnen. Oder es steht ein constexpr constructor eine OneWireId Klasse
da, der die CRC-Berechnung zur Compilezeit macht.
Das ist nur ein kleines Beispiel.
Man kann z.B. auf STM32 4 Bits eines LCD-Daten-"Worts" beliebig auf
einem 16bit-Port anordnen und zur Compile-Time eine LUT mit 16 Werten
für das BSRR (Bit Set/Reset Register) erzeugen, die dann per "echten
Wert" indiziert, die passenden Pins befüllt. Wohlgemerkt beliebige
Verteilung der Pins innerhalb des Ports.
Bei jedem dieser Beispiele bekommt man dann von "mitfiebernde"
anerkennende Wort, von den anderen die Ausrede, das geht doch in xyz so
und muß nicht anders sein.
Wenn es so wäre, daß nicht die Summe der komplizierten Detail unser
Rechenspielzeuge ausmachen würde, dann wäre ein Abakus immer die beste
Lösung.
Possetitjel schrieb:> Markus F. schrieb:>>> "Rummäkler" mäkeln meiner Ansicht nach oft genug>> lediglich aus verletzter Eitelkeit mit Neid ("der>> kann was, was ich nicht mal verstehe, das muss>> also akademischer Mist sein").>> Die Unverständlichkeit vieler Computerthemen ist> meiner Erfahrung nach nicht ihrer tatsächlichen> Kompliziertheit geschuldet, sondern der Unfähigkeit> bzw. der Unlust der Missionare, sich allgemein-> verständlich auszudrücken.
In seltene Fällen aber auch am Unvermögen bzw der Unlust der
Missionierten, sich auf neues einzulassen.
> Die Geschichte der Informatik ist die Geschichte> schlechter Begriffsbildungen und hirnrissiger> Erklärungen.
Die ganze Geschichte von Wissenschaft und Technik zeigt, daß es auch mal
ein/zwei Generationen Dauern kann, bis Spezialwissen zum Allgemeingut
wird. Im Mittelalter wäre man für das Verbreiten von C++-Knowhow
verbrannt worden.
> Wenn ich Potenzial hinter einem Konzept erkenne, bin> ich durchaus lernwillig. Ich bin aber nicht bereit,> als Initiationsritus unter Schmerzen irgend einen> Gehirnkrampf auswendig zu lernen, nur um dazuzugehören.
Manchmal kann der Erkenntnisstand der "Pioniere" aber nicht auf
Nachzügler warten.
Possetitjel schrieb:> Markus F. schrieb:>>> "Rummäkler" mäkeln meiner Ansicht nach oft genug>> lediglich aus verletzter Eitelkeit mit Neid ("der>> kann was, was ich nicht mal verstehe, das muss>> also akademischer Mist sein").>> Die Unverständlichkeit vieler Computerthemen ist> meiner Erfahrung nach nicht ihrer tatsächlichen> Kompliziertheit geschuldet, sondern der Unfähigkeit> bzw. der Unlust der Missionare, sich allgemein-> verständlich auszudrücken.
Jede Fachdisziplin hat ihr eigenes Idiom. Die Mediziner sind da ganz
weit "vorn", indem sie ihre Idiome in Latein/Griechisch ausdrücken. Dei
den Informatikern ist es überwiegend Englisch, wenn man "pipe" nicht mit
"Rohr" zwanghaft ins Deutsche übersetzen will.
Wir reden von Klassen, Funktionen, Elementfunktionen, Methode,
Nachricht, Datentypen, abstrakte Datentypen, generische Datentypen,
Objekten, Instanzen, Exemplaren und alles hat eine ziemlich festgelegte
Bedeutung. Je nach Kontext kann die eine oder andere Ausprägung eines
Begriffes im Vordergrund stehen.
Im allgemeinen ist es verständlicher, sich in dem zur Fachdisziplin
gehörenden Idiom auszudrücken, weil es prägnanten ist und man deswegen
weniger umschreiben muss: man sagt einfach "FiFo" oder "FiFo-ordered
Queue" statt: die Datenstruktur, die zwei (mindestens) Operationen
anbietet; eine, um Elemente anzufügen und eine, um Elemente zu
entfernen.
> Die Geschichte der Informatik ist die Geschichte> schlechter Begriffsbildungen und hirnrissiger> Erklärungen.
Beispiele?
Carl D. schrieb:> Das Prinzip von unterschiedlichen fixen und variablen Kosten und der> Punkt (meist etwas oberhalb von trivial) an dem "wenig fix/viel> variabel" Dei Variante "viel fix/wenig variabel" kostenmäßig überholt,> sollte auch nicht-BWLern geläufig sein.
Mag sein, daß man für größere Projekte tatsächlich C++ braucht. Aber
kleinere Projekte wie etwa der Linuxkernel mit 25 Millionen Codezeilen
gehen auch ganz gut in C, dann hat man auch nicht den ganzen Quatsch von
C++.
Wilhelm M. schrieb:> Possetitjel schrieb:>> Markus F. schrieb:>>>>> "Rummäkler" mäkeln meiner Ansicht nach oft genug>>> lediglich aus verletzter Eitelkeit mit Neid ("der>>> kann was, was ich nicht mal verstehe, das muss>>> also akademischer Mist sein").>>>> Die Unverständlichkeit vieler Computerthemen ist>> meiner Erfahrung nach nicht ihrer tatsächlichen>> Kompliziertheit geschuldet, sondern der Unfähigkeit>> bzw. der Unlust der Missionare, sich allgemein->> verständlich auszudrücken.>> Jede Fachdisziplin hat ihr eigenes Idiom.
Klar. Präzise Fachsprache ist wichtig und sinnvoll.
> Die Mediziner sind da ganz weit "vorn", indem sie ihre> Idiome in Latein/Griechisch ausdrücken.
Sehr gutes Beispiel: In der Medizin kann man am lebenden
Objekt studieren, wie man Sprache als Waffe verwendet, um
sich abzugrenzen und anderen auszuschließen.
(Soweit ich weiss, war das Ziel, vom Status des Jahrmarkts-
gauklers wegzukommen und sich äußerlich sichtbar der
Gelehrtenwelt anzugliedern, ein wesentlicher Grund dafür,
dass Chirurgen und ähnliche Leute begonnen haben, Lateinisch
zu reden. Es ging dabei nicht nur um Fachsprache, sondern
sehr wesentlich auch um sozialen Status. Und das hat, wie
man an den "Göttern in Weiss" sieht, auch funktioniert.)
> Dei den Informatikern ist es überwiegend Englisch, wenn> man "pipe" nicht mit "Rohr" zwanghaft ins Deutsche> übersetzen will.
Ich habe mit dem Englischen als "lingua franca" der modernen
Technik meinen Frieden gemacht. Das ist nicht mein Punkt.
> Wir reden von Klassen, Funktionen, [...]
Dazu unten mehr.
>> Die Geschichte der Informatik ist die Geschichte>> schlechter Begriffsbildungen und hirnrissiger>> Erklärungen.>> Beispiele?
Unzählige.
Wenn man als Einstieg mal bei Wikipädie "Programmierparadigma"
nachschlägt, dann findet man einen Berg von Geschwurbel vor,
der eines schlechten literaturwissenschaftlichen Seminars
würdig wäre. Das liegt aber nicht daran, dass die WP-Autoren
dumm wären, sondern daran, dass sich auch außerhalb der
Wikipädie niemand die Mühe gemacht hat, das hinterliegende
Konzept klar und deutlich herauszuarbeiten.
Und das Konzept ist: Programme beschreiben Automaten.
In der klassischen Ära (FORTRAN) beschrieb das Programm im
Wesentlichen einen großen Automaten; die Steuerstruktur
bestand aus GOTO, und die Variablen waren global.
Die strukturierte Programmierung ging auf die Kombinatorik
des Automaten los und legte Regeln zu dessen Strukturierung
fest; als Ergebnis dessen liegen (in Form der Prozeduren und
Funktionen) viele kleine kombinatorische Schaltnetzwerke mit
klar definierten Schnittstellen vor, die (durch Aufruf) zur
Laufzeit miteinander verschaltet werden können.
Der nächste (offensichtliche) Schritt ist die modulare
Programmierung; sie überträgt den Gedanken der Zerlegung in
handliche Teile von der Kombinatorik des Automaten auf die
Flipflop-Batterie und bildet, indem sie Flipflops und
Kombinatorik gemeinsam KAPSELT, erstmals echte Teilautomaten.
Die objektorientierte Programmierung geht hier insofern noch
einen Schritt weiter, als dass sie es erstmals ermöglicht,
zur Programmlaufzeit eine erst zur Laufzeit wählbare Anzahl
an Exemplaren desselben Automatentyps zu erzeugen. In dieser
Sichtweise ist weder die Vererbung noch die Kapselung eine
echte artbildende Eigenheit der OOP, sondern die Tatsache,
dass man Objekte zur Laufzeit erzeugen und vernichten kann.
Objekte als gekapselte Zusammenfassung von Daten und Code
sind also schlicht und ergreifend Automaten (die ja aus
einer Kombinatorik und einer Flipflop-Batterie bestehen),
und ein objektorientiertes Programm beschreibt ein Automaten-
netz.
Das Riesentamtam, das um die Detail der Vererbung (Mehrfach-
vererbung, Diamond-Problem) gemacht wird, ist in dieser Sicht
ein aufgebauschtes bürokratisches, verwaltungstechnisches
Problem, das man auch entsprechend behandeln sollte. OOP
geht auch ohne Vererbung -- also sind Vererbungsprobleme
keine immanenten OOP-Probleme.
Die Modellvorstellung "Programme beschreiben Automatennetze"
hat noch einen anderen Vorteil.
Als ich mich vor Jahren mit einem Kollegen, der im Gegensatz
zu mir einschlägige Vorlesungen gehört hatte, über VHDL
unterhielt, sagte dieser einen geradezu prophetischen Satz:
"Ach weisst Du, das ist im Prinzip genau wie C... nur es
passiert eben alles gleichzeitig."
Die Vorstellung "Programme beschreiben Automatennetze"
hat den großen Vorzug, dass sie von der (längst nicht
mehr gültigen) technischen Zufälligkeit einer sequenziellen
Maschine abstrahiert. Dabei gibt es zwei praktisch wichtige
Entwicklungsrichtungen:
Zum einen ist da das Multitasking, dessen Kern ja darin liegt,
das zahlreiche unabhängige ("virtuelle") Automaten auf dieselbe
Hardware abgebildet werden und gleichzeitig ohne sich zu stören
arbeiten. Extremstes Beispiel ist die SPS, die perfektes
Multitasking bietet, ohne den Begriff überhaupt zu kennen.
(Wer mal bei der Inbetriebnahme einer Rundtischmaschine mit
16 Stationen und hunderten Aktoren dabeiwar, weiss, was ich
meine. Wenn es hierbei einen "Crash" gibt, dann gibt es WIRKLICH
einen Crash.)
Zum anderen ist auch der Prozessor selbst längst keine rein
sequenzielle Maschine mehr; man hält lediglich an diesem
Programmiermodell fest, weil man noch kein besseres hat, das
für den Masseneinsatz tauglich wäre. Tatsächlich macht ein
üblicher PC-Prozessor ja vieles parallel, was im Programm
m.o.w. sequenziell beschrieben ist. Wenn man diese Gedanken-
schiene weiterfährt, landet man bei VHDL.
Zwei abschließende Gedanken zu diesem Teilast. Erstens: Mir
ist inzwischen klar, dass man Berechenbarkeit nicht nur mit
Bezug auf den Turing-Automaten als Modellmaschine erklären
kann, sondern auch über den Lambda-Kalkül. Wie die Brücke
von der Automatentheorie zum Lambda-Kalkül aussieht, ist mir
noch nicht klar. Lisp/Scheme/Tcl sind aber der Beweis dafür,
dass diese Frage praktisch relevant ist.
Zweitens: Auch die Brücke vom "Standard-Modell der Informatik"
(der Turing-Maschine, die ja sequenziell arbeitet) zur von
mir ständig zitierten Automatentheorie ist u.U. nicht auf
den ersten Blick offensichtlich. Man kann sich aber leicht
vorstellen, dass die Automaten durch boolesche Gleichungen
beschrieben werden können, welche wiederum durch die Turing-
Maschine sequenziell ausgewertet werden. Das führt auf das
interessante Thema, dass durch fehlerhafte Auswertung an sich
korrekter Gleichungen "parasitäre" Zustände entstehen, die
z.B. zu unerwünschten Blockierungen führen (Stichwort
"Warteschleifen und Nebenläufigkeit").
So. - Du schreibst oben, man spräche von Klassen, Methoden,
Elementfunktionen und so weiter.
Richtig. Um meine Kritik aggressiv zu formulieren: Die
praktischen Informatiker führen sich wie die spanischen
Eroberer oder die amerikanischen Siedler auf, die irgendwo
einfallen, alles niederbrennen, ihr eigenes Getreide säen
und sich einen feuchten Kehricht dafür interessieren, was
lange vor ihrem Einfallen dort schon an Interessantem
gewachsen ist.
Eine "Funktion" (im Sinne der Informatik) ist einfach eine
Kombinatorik (kombinatorischer Automat).
Ein "Objekt" ist ein Automat.
Eine "member function" ist eine zu einem Automaten gehörende
Kombinatorik.
Eine "Klasse" ist der Schaltplan eines (abstrakten) Automaten.
Eine "Instanz" ist ein konkretes Exemplar eines abstrakten
Automaten, das nach dem gültigen Schaltplan hergestellt wurde.
Nach meiner Wahrnehmung werden Sprachkonstrukte immer nur mit
Verweis auf die Theorie der Programmiersprachen erklärt. Das
kommt den Informatikern offenbar völlig natürlich vor, ist aber
deshalb fatal, weil die Programmiersprachen selbst auch nur ein
HILFSMITTEL sind -- sie dienen nämlich dazu, das VERHALTEN VON
AUTOMATEN zu beschreiben!
Die Informatiker sollten also diesen inzestuösen Rahmen, in
dem Sprachkonstrukte immer nur durch Begriffe aus der Theorie
der Programmiersprachen beschrieben werden, endlich mal ver-
lassen, und sich auf die viel relevantere Frage konzentrieren,
welchen neuen AUTOMATENSTRUKTUREN ich mit diesen Sprach-
konstrukten beschreiben kann, und warum das nützlich ist.
Carl D. schrieb:> Manchmal kann der Erkenntnisstand der "Pioniere" aber> nicht auf Nachzügler warten.
Es geht nicht um den Erkenntnisstand an sich, sondern
um die Unfähigkeit oder die Unlust, die unter vielen
persönlichen Mühen gewonnenen Erkenntnisse so umzuformu-
lieren, dass sie für andere leicht verständlich werden.
Edison sage, Genie sei 1% Inspiration und 99% Transpiration.
Die geniale Erkenntnis zu haben ist 1%, sie verständlich
zu formulieren und lehrbar zu machen, die restlichen 99%.
Hallo,
Possetitjel schrieb:> Die Informatiker sollten also diesen inzestuösen Rahmen, in> dem Sprachkonstrukte immer nur durch Begriffe aus der Theorie> der Programmiersprachen beschrieben werden, endlich mal ver-> lassen, und sich auf die viel relevantere Frage konzentrieren,> welchen neuen AUTOMATENSTRUKTUREN ich mit diesen Sprach-> konstrukten beschreiben kann, und warum das nützlich ist.
Du hast es perfekt zusammengefasst.
Das trifft allerdings nicht nur auf die "Programmierspracheninformatik"
zu, sondern findet sich immer mehr in anderen technischen Bereichen
wieder.
rhf
Possetitjel schrieb:
Frei nach dem Motto: ich schreibe eine lange Antwort, weil keine Zeit
hatte, mich kurz zu fassen.
> Und das Konzept ist: Programme beschreiben Automaten.
Nun, das lernen Informatiker typischerweise am ersten Tag.
> Nach meiner Wahrnehmung werden Sprachkonstrukte immer nur mit> Verweis auf die Theorie der Programmiersprachen erklärt. Das> kommt den Informatikern offenbar völlig natürlich vor, ist aber> deshalb fatal, weil die Programmiersprachen selbst auch nur ein> HILFSMITTEL sind -- sie dienen nämlich dazu, das VERHALTEN VON> AUTOMATEN zu beschreiben!
s.o.
Wilhelm M. schrieb:> Possetitjel schrieb:>> Frei nach dem Motto: ich schreibe eine lange Antwort,> weil keine Zeit hatte, mich kurz zu fassen.
Du irrst -- das IST die Kurzfassung.
Sie ist so lang geworden, weil ich den roten Faden klar
darstellen wollte.
>> Und das Konzept ist: Programme beschreiben Automaten.>> Nun, das lernen Informatiker typischerweise am ersten> Tag.
Mag wohl sein, dass sie es lernen -- aber sie begreifen
es nicht.
Sie lernen, dass es eine Korrespondenz zwischen den
Chomsky-Grammatiken und bestimmten Automatenklassen gibt.
Soweit stimmt das.
Die logische Umkehrung dieses Gedankens, dass ein Satz in
einer gegebenen Chomsky-Grammatik (vulgo: ein Programm)
dann auch genau einen bestimmten Automaten beschreiben
muss, habe ich noch NIRGENDWO gelesen. Nirgends. Das ist
den akademischen Theoretikern viel zu trivial, als dass
man es aufschreiben dürfte.
Selbstverständlich ist diese Umkehrung aus theoretischer
Sicht trivial -- sie ist aber aus praktischer Sicht
entscheidend, weil sie die Grundlage für meine anschauliche
Vorstellung ist: Ich darf mir JEDES Programm als Zusammen-
schaltung von 74HCxx-ICs vorstellen. Es ist mathematisch
beweisbar, dass diese Deutung zulässig ist!
Du hast Dich oben beklagt, dass Deine Versuche, C++ und
seine Vorteile zu popularisieren, so stark auf Ablehnung
stoßen. Ich habe versucht, die Ursache für diese Ablehnung
zu ergründen, indem ich meine eigenen Gedanken und Eindrücke
niederschreibe.
Etwas kürzer als oben würde ich so sagen:
Du zitierst (aus meiner Sicht zu Recht) die Forderung "stop
teaching C". Du wirst ihr aber nicht gerecht, denn Du lehrst
C++ genau so, wie all die furchtbaren C-Lehrbücher C lehren!
Du springst -- genau wie die Lehrbücher -- kopfüber in die
Details der Sprache, die festlegen, WIE man Sachverhalte
formuliert, statt Dich erstmal ausführlich bei dem (für Dich
entsetzlich langweiligen und trivialen) Thema aufzuhalten,
WAS man in der Sprache eigentlich FORMULIERT!
Die Antwort auf diese Frage sollte nämlich NICHT "einen
Algorithmus" lauten, sondern "einen Automaten". (Eigentlich
"ein Automatennetz". Egal.) Das ist nämlich MEINER Meinung
nach das Wesentliche am Programmieren.
So. Jetzt gibt es das andere Problem: Wer C gelernt hat, bei
dem ist das Kind schon in den Brunnen gefallen, denn der hat
bereits verinnerlicht, dass man in einer Programmiersprache
"selbstverständlich" einen Algorithmus formuliert, also eine
Vorschrift, die nach endlich vielen Schritten zum Ergebnis
führt. Die (theoretisch zweitrangige) Prämisse der sequenziellen
Verarbeitung ist unauslöschlich in sein Hirn eingebrannt. Man
müsste also aus dieser Sackgasse erstmal rückwärts herausfahren
und den Gedanken popularisieren, dass man auch in klassischem
C das Verhalten von AUTOMATEN beschreibt, denn dann hat man
konkrete Anknüpfungspunkte für die Demonstration, wieso man
dieses und jenes in C++ BESSER als in C beschreiben kann.
Überspitzt ausgedrückt: Man muss auch beim Lehren von C die
Prämisse "stop teaching C" beherzigen!
Oder das Ganze NOCH kürzer:
Vieles, was über Programmierung gesagt wird, suggeriert, das
Programm beschriebe direkt die Sachverhalte der Anwendungs-
domäne.
Das ist Schwachsinn. Der Programmierer bildet die Sachverhalte
der Anwendungsdomäne in einen abstrakten Automaten ab, und
DIESER AUTOMAT wird mit den Mitteln der Programmiersprache
beschrieben. Die Gesamtabbildung ist nicht einstufig, sondern
zweistufig.
Nur diese Tatsache macht es möglich, unterschiedliche
Programmiersprachen einigermaßen effizient miteinander zu
vergleichen.
Possetitjel schrieb:> Ich darf mir JEDES Programm als Zusammen-> schaltung von 74HCxx-ICs vorstellen. Es ist mathematisch> beweisbar, dass diese Deutung zulässig ist!
Als Automaten-Theorie, Turing-Maschine oder gar Lambda-Kalkül erfunden
wurden, gab es noch gar keine 74er-IC's, oder überhaupt irgendwelche
Halbleiter. Tatsächlich hat die Informatik mit völlig abstrakten
Beschreibungen von mathematischen Algorithmen angefangen, als es
nichtmal Röhren gab. Die Informatiker haben hier also definitiv nicht
wie Conquistadores die schönen Konstruktionen der Ingenieure
durcheinander gebracht. Vor allem der Lambda-Kalkül ist komplett
losgelöst von Dingen wie "Zustände" (Flipflops) und sequentieller
Ausführung, auch wenn er bijektiv auf Turing-Maschinen abbildbar ist.
Ausgehend von dieser theoretischen Basis wurden Programmiersprachen,
Parser und auch heutige Bestandteile der Informatik entwickelt. Ob die
jetzt auf Papier&Stift, Mechanische Rechner, Röhren-Rechner, 74er-Gräber
oder integrierte CPU's ausgeführt werden ist komplett egal.
Viele der Begriffe wie "Klasse" oder "Funktion" kommen aus der
Mathematik (Informatik = Informations-Mathematik), und klingen daher
Un-Ingenieurisch, aber sind sie deswegen falsch?
Unbestritten ist in der Mathematik "f(x)=7*x" eine Funktion. In C wäre
das dann z.B.
1
doublef(doublex){return7.*x;}
Soll man das jetzt nicht mehr Funktion nennen? Soll man es Automaten
nennen obwohl es überhaupt keinen Zustand ("Flipflops") hat?
Auch wenn es richtig ist dass prinzipiell jedes Programm einen Automaten
beschreibt, braucht man dennoch höhere Abstraktionen, ja, Bürokratie, um
der Komplexität Herr zu werden. Daher gibt es Datenstrukturen, welche
Daten (und Daten sind ja das, um das sich alles dreht) als Black Boxen
kapseln. Dafür ist OOP, inklusive Dingen wie Vererbung, ein
erwiesenermaßen äußerst nützliches Hilfsmittel. Dinge wie Interfaces
scheinen nutzlose Bürokratie zu sein; genau wie der Dienstweg in
komplexen Organisationen. Aber ohne versinkt schnell alles im Chaos. OOP
geht auch in C und wird auch gemacht, z.B. im Linux-Kernel.
Würdest du auch Programme in rein funktionalen Sprachen als Automaten
bezeichnen? Diese enthalten keine Anweisungen, beschreiben keinen
Zustand, verändern keine Daten, lassen sich nur nichttrivial auf
tatsächliche Rechner umsetzen, die wie "Automaten" aufgebaut sind. Sie
bieten nur ein Mapping Eingabe->Ausgabe. Dennoch kann man alles damit
berechnen.
Es ist übrigens sehr lehrreich mal 1-2 Module theoretische Informatik zu
besuchen; dort werden die mathematischen Wurzeln der Informatik offenbar
und warum die Informatik sich eben nicht als Hilfswissenschaft für
Ingenieure sieht.
Außerdem finde ich dass die Ingenieurs-Wissenschaften auch nicht
besonders zugänglich sind. Unmengen an kaputt-missbrauchter Mathematik
und ebenso abgehobenen Begriffen machen die auch nicht leichter
verständlich.
Überhaupt ist es spannend, wie hier (vermutlich) Ingenieure immer wieder
erklären wie sie alles besser wissen als Informatiker. Machen andere
Fachbereiche so etwas auch? Haben solche Ingenieure überhaupt genügend
Informatik-Wissen um darüber urteilen zu können?
Jetzt trete ich mal (wie schon so oft) kräftig ins Fettnäpfchen:
Ich lese ja gerne mit und nichts liegt mir ferner als "Religion" zu
machen. Von meiner begrenzten Vista kann ich nur kommentieren, daß die
moderne Sprachenevolution höchstwahrscheinlich ihre Berechtigung und
Grund hat um komplizierte (moderne) Probleme besser lösen zu können.
Ich sehe es an mir, bei den C++ Beispielen blicke ich ohne weitgehende
Recherche nicht mehr durch. Mein Gehirn ist total auf das klassische
Programmieren eingerastet. Klassische Sprachen verstehe ich. Ich muß
alles verstehen und komplett sehen können. Bei Klassischen C u.ä. tut
man sich da leicht. Wenn ich mir aber das neueste C++ ansehe kann ich
die klare Logik nicht mehr verfolgen. Sorry. Es geht einfach nicht. Das
ist mir dann zu abstrakt und versteckt. C++ auf Niveau z.B vieler
Arduino Bibliotheken kann ich noch einigermaßen verstehen. Die neuesten
Konzepte sind mir aber im Augenblick einfach noch zu abstrakt.
Da bei mir der Schwerpunkt meines Interesses auf uC liegt, komme ich
praktisch mit C sehr gut zurecht. Hier schwimme ich in meinem
natürlichen Element. Mit C++ bin ich zur Zeit noch aus meinem Element
heraus.
Was ich damit sagen will ist, daß wahrscheinlich nur Leute mit den neuen
Konzepten wirklich glücklich werden die noch nicht mit klassischen
Programmieren vorbelastet sind. Wer also mit C++ und Objekt Konzepten
groß wird für den ist das höchstwahrscheinlich intuitiv. Klassisches
Programmierverständnis hindert hier massiv. Wer so wie ich mit
klassischen Programmieren groß geworden ist, tut sich oft schwer so weit
umzudenken. Auch wenn ich mir Mühe gebe, AHA Momente sind leider nur
spärlich. Tut mir leid, es ist aber so.
Dann kommt noch dazu, daß man viel neuen Syntax und Konzepte lernen muß
und sehr viel Zeit mit Studium der neuen Sprachen verbringen muß. Auch
kenne ich niemand in meinem Umfeld der zusammen mit mir mal ein kleines
praktisches Lehrprojekt machen würden.
Wenn es möglicherweise anderen ähnlich wie mir geht, dann müßte man
daraus schließen, daß wenn dazu lernen nicht wirklich funktioniert man
eben das akzeptieren sollte und mit den Methoden die man beherrscht die
anfallenden Probleme lösen sollte. Ich fürchte, auch wenn ich mir sehr
viel Mühe gebe würde, daß der Groschen einfach nicht bald genug fallen
würde.
Nicht jeder muß für eine Firma arbeiten, die darauf besteht, daß man die
gängigen Sprachen beherrscht um kommerziell damit arbeiten zu können.
Deshalb finde ich es besser mit dem Missionarisieren hier im Forum gar
nicht erst anzufangen und sich gegenseitig zu respektieren. Ich finde
jedenfalls die vorgestellten Beispiele durchaus interessant und plane
mich auch etwas damit zu befassen sobald meine Tool Chain funktioniert.
Aber meine eigenen Projekte ziehe ich lieber so durch wie ich es eben
gelernt habe.
So ihr seht, bei mir ist, wie man sagt, Hopfen und Malz verloren:-)
Also, macht weiter. Interessieren tut es mich schon was auf dem Gebiet
der C++ Entwicklung so gemacht wird und zeigt wie man Probleme
heutzutage löst.
Ich hoffe ich habe mich hier mit meinem Kommentar nicht zu sehr
blamiert. Aber ich wollte nur mal berichten wie es von der anderen Seite
des Zauns aussieht...
Schönen Tag noch,
Gerhard
Das beschreibt ziemlich eindeutig einen Automaten. Es werden
nacheinander Daten-manipulierende Befehle abgearbeitet. In C++ und
vielen anderen Sprachen sieht das so aus:
Hier sieht man nicht mehr viel vom Automaten auch wenn die Hardware
letztendlich einer ist. Ist es hier nicht viel sinnvoller in Form von
Funktionen und Datenstrukturen zu denken? Die string-Klasse kapselt
Daten, die greeting-Funktion bildet Daten auf andere Daten ab. Das auf
Logik-IC's umzusetzen erfordert schon ziemliche Hirn-Verrenkungen, die
hier nicht besonders nützlich sind.
Übrigens nutzt auch std::string die böse template-Metaprogrammierung,
aber als Nutzer sieht man davon nichts.
Gerhard O. schrieb:> Wer also mit C++ und Objekt Konzepten> groß wird für den ist das höchstwahrscheinlich intuitiv.
OOP stammt aus den 60ern/70ern, und C++ aus den 80ern... Wann hast du
denn programmieren gelernt?
Dr. Sommer schrieb:> Gerhard O. schrieb:>> Wer also mit C++ und Objekt Konzepten>> groß wird für den ist das höchstwahrscheinlich intuitiv.>> OOP stammt aus den 60ern/70ern, und C++ aus den 80ern... Wann hast du> denn programmieren gelernt?
In den 80er Jahren. Motorola 6800 ASM, HP-BASIC/QB45/7, viel
Instrumentsteuerung mit HP-IB, 8051 Assembler, Delphi., C. LabVIEW.
Also alles Zeugs um man sich heutzutage nicht mehr viel schert. Altes
Eisen...
Auch wenn, wie Du sagst die Grundlagen "modern" implementierter Konzepte
teils schon betagt sind, bin ich damit nie konfrontiert worden. Formell
habe ich mich also mit den heutigen Mainstream Werkzeugen nie damit
befaßt. Machte also nur HW und embedded Sachen. Man bleibt eben oft
lieber auf dem familiären Pfad. Für mich sind das eben die erwähnten
Werkzeuge. Sachen wie Lambda Kalkül sind für mich leider ein Fremdwort.
Abgesehen davon habe ich mich damals hauptsächlich mit diskreten Logik
Design befasst und viel Analog und Funktechnik. Programmieren war nur
Mittel zum Zweck um Mikroprozessor/uC einsetzen zu können. Und das
machte man damals eben mit ASM und C. Es bestand nie eine Notwendigkeit
viel über den Tellerrand zu schauen weil die Werkzeuge die man kannte
eben ausreichend waren um die anfallenden Probleme zu bewältigen. Man
könnte auch dazu sagen, man stagnierte:-)
Na, dann bist du auch ein bisschen selber schuld die "modernen"
Techniken nicht zu kennen :-)
Das Lambda-Kalkül ist eine der ersten Programmiersprachen, praktisch der
Prototyp aller funktionalen Sprachen, aus den 30er-Jahren. Sie hat keine
praktische Bedeutung, ist aber theoretische Grundlage für viele wichtige
Konzepte. Spannend daran ist dass die Sprache extrem simpel ist und noch
nicht einmal Zahlen kennt, man damit aber dennoch alles berechnen kann
(ist äquivalent zur Turing-Maschine) - "rechnen mit nichts".
Dr. Sommer schrieb:> Hier noch ein Beispiel, eine einfache String-Konkatenation welche auch> 0-Bytes können soll. In C:
Also auf jeden Fall eleganter und "Powerful" sieht das zweite Beispiel
schon aus. Nur verstehe ich im Augenblick nicht wie es unter der Haube
funktioniert. Da müßte man schon mit der String Library vertraut sein.
Da scheint der Compiler die notwendige Funktionalität des Ausdruckes
anhand des Syntax selber zu konstruieren anstatt eine traditionelle C
String Funktion wählen zu müssen. Sehe ich das richtig oder rede ich
hier Stuss?
Aber es illustriert wie man sich auf die Anwendung beschränken kann und
sich nicht mit Implementierungsdetails verzetteln muß.
Gibt es Version vom GCC mit dem das auc auf uC funktionieren würde?
Wilhelm warf ein, daß teilweise das nur auf größeren Systemen anwendbar
ist und auf AVR es im Augenblick anscheinend noch nicht verfügbar ist.
Dr. Sommer schrieb:> Na, dann bist du auch ein bisschen selber schuld die "modernen"> Techniken nicht zu kennen :-)> Das Lambda-Kalkül ist eine der ersten Programmiersprachen, praktisch der> Prototyp aller funktionalen Sprachen, aus den 30er-Jahren. Sie hat keine> praktische Bedeutung, ist aber theoretische Grundlage für viele wichtige> Konzepte. Spannend daran ist dass die Sprache extrem simpel ist und noch> nicht einmal Zahlen kennt, man damit aber dennoch alles berechnen kann> (ist äquivalent zur Turing-Maschine) - "rechnen mit nichts".
Ich habe mir das Wiki dazu durchgelesen. Leider verstehe ich von der
Unterliegenden Mathe zum Teil nur Bahnhof. Das ist mir zu theoretisch.
Gerhard O. schrieb:> Nur verstehe ich im Augenblick nicht wie es unter der Haube> funktioniert.
Die Idee ist, dass man das auch nicht muss. Wenn man komplexe Systeme
hat kann man unmöglich jede Komponente begreifen...
Gerhard O. schrieb:> Da scheint der Compiler die notwendige Funktionalität des Ausdruckes> anhand des Syntax selber zu konstruieren
Gewissermaßen... Die string-Klasse definiert einen eigenen "+"-Operator
welcher alles Notwendige erledigt. Ist im Endeffekt eine Funktion mit
komischem Namen, die hier aufgerufen wird.
Gerhard O. schrieb:> Gibt es Version vom GCC mit dem das auc auf uC funktionieren würde?
Leider nicht. Die string-Klasse benötigt dynamischen Speicher, der auf
kleinen AVR's problematisch ist. Man könnte sich etwas basteln (mit mehr
templates...) was dort einsetzbar ist aber dann natürlich eingeschränkte
Funktionalität hat. Vielleicht würde es reichen einen eigenen Allokator
zu übergeben, ich hab das noch nicht versucht...
Gerhard O. schrieb:> Ich habe mir das Wiki dazu durchgelesen. Leider verstehe ich von der> Unterliegenden Mathe zum Teil nur Bahnhof. Das ist mir zu theoretisch.
Ja, für praktische Anwendung bringt das eh nichts. Wenn du mit
funktionaler Programmierung anfangen möchtest kannst du dir Sprachen wie
Lisp, Scala, Haskell, ... anschauen.
Dr. Sommer schrieb:> Possetitjel schrieb:>> Ich darf mir JEDES Programm als Zusammen->> schaltung von 74HCxx-ICs vorstellen. Es ist mathematisch>> beweisbar, dass diese Deutung zulässig ist!>> Als Automaten-Theorie, Turing-Maschine oder gar Lambda-Kalkül> erfunden wurden, gab es noch gar keine 74er-IC's,
Das war auch nicht meine Aussage.
> oder überhaupt irgendwelche Halbleiter.
Ich kenne durchaus Namen wie Zuse oder Babbage, und ich kenne
auch die Geschichten rund um die Enigma. Ach so... "Dreloba"
sagt Dir etwas?!
> Die Informatiker haben hier also definitiv nicht wie> Conquistadores die schönen Konstruktionen der Ingenieure> durcheinander gebracht.
Du missverstehst mich. Die "praktischen Informatiker"
haben das Land der Mathematiker und Logiker verwüstet.
Was ich oben über Programmierparadigmen schrieb, habe ich
mir ja zum größten Teil nicht selbst ausgedacht, sondern
mir nur mit unendlicher Mühe aus einigen wenigen sehr guten
Theoriebüchern zusammengeklaubt: Logik, Compilerbau, theo-
retische Informatik.
Die echt harte Arbeit bestand darin, die sehr nützlichen
theoretischen Begriffe in die Praxis rückzuübertragen.
In den Büchern über Programmierung und Programmiersprachen
findet man davon nämlich nix. Die verzetteln sich in den
sprachlichen Einzelheiten, die die Konzepte mehr verdecken
als erklären.
> Vor allem der Lambda-Kalkül ist komplett losgelöst von> Dingen wie "Zustände" (Flipflops) und sequentieller> Ausführung, [...]
GENAU DAS schrieb ich (in etwas anderen Worten) in meinem
ersten Beitrag.
> Viele der Begriffe wie "Klasse" oder "Funktion" kommen> aus der Mathematik (Informatik = Informations-Mathematik),> und klingen daher Un-Ingenieurisch, aber sind sie deswegen> falsch?
Nein -- nicht deswegen.
Sie sind deswegen furchtbar, weil die praktischen Informatiker
die Mathematik so verhuntzen. Korrigiere mich, wenn ich falsch
liege, aber eine C-function, die eine static-Variable enthält,
ist doch genau KEINE zustandsfreie Funktion mehr, oder?
> Unbestritten ist in der Mathematik "f(x)=7*x" eine Funktion.> In C wäre das dann z.B.double f (double x) { return 7. * x; }> Soll man das jetzt nicht mehr Funktion nennen?
Kommt auf den Kontext an.
> Soll man es Automaten nennen obwohl es überhaupt keinen> Zustand ("Flipflops") hat?
Das wäre durchaus ein sinnvoller Anfang. Wenn man weiter
vorn erklärt hat, was Automaten sind, ist die Auffassung
einer reinen Kombinatorik als Grenzfall eines Automaten
("entarteter Automat") sinnvoll, ja. Genauso ist ja die
Auffassung eines reinen Flipflops als Automaten ohne
weitere Kombinatorik sinnvoll.
> Auch wenn es richtig ist dass prinzipiell jedes Programm> einen Automaten beschreibt, braucht man dennoch höhere> Abstraktionen, [...]
Selbstverständlich. Dagegen habe ich nichts.
Ich habe überhaupt nichts gegen höhere Abstraktion, wenn
zuvor die einfachen, leicht zugänglichen Modelle und
Vorstellungen erklärt würden.
> Würdest du auch Programme in rein funktionalen Sprachen> als Automaten bezeichnen?
Nein -- es SIND keine Automaten, aber sie beschreiben das
VERHALTEN von Automaten. Genau DAS wird ja durch die
bijektive Abbildbarkeit auf die Turing-Maschine garantiert!
Und genau DESWEGEN ist die Vorstellung mit den Automaten
so genial: Sie klappt auch, wenn "in Wahrheit" gar keine
Automaten da sind!
> Es ist übrigens sehr lehrreich mal 1-2 Module theoretische> Informatik zu besuchen; dort werden die mathematischen> Wurzeln der Informatik offenbar und warum die Informatik> sich eben nicht als Hilfswissenschaft für Ingenieure sieht.
Mir ist relativ egal, wie sich die Informatiker selbst sehen.
Die theoretische Informatik steht sicher der Logik und der
Mathematik näher als den Ingenieurswissenschaften -- ganz
wie das auch in der theoretischen Elektrotechnik ist.
Die praktische oder angewandte Informatik IST für mich eine
Ingenieursdisziplin, genauso wie die Elektrotechnik.
> Außerdem finde ich dass die Ingenieurs-Wissenschaften auch> nicht besonders zugänglich sind. Unmengen an kaputt-> missbrauchter Mathematik und ebenso abgehobenen Begriffen> machen die auch nicht leichter verständlich.
Mag sein... da bin ich sicher nicht der optimale Gesprächs-
partner; was die Elektrotechnik angeht, bin ich naturgemäß
sehr voreingenommen.
In einem gebe ich Dir aber Recht: Gute Dozenten sind rar,
und wirklich gute Lehrbücher auch. Die Suche wird nur etwas
vereinfacht, weil die Disziplinen schon etwas älter sind als
die Informatik, und sich die Spreu schon mehr vom Weizen
getrennt hat.
> Überhaupt ist es spannend, wie hier (vermutlich) Ingenieure> immer wieder erklären wie sie alles besser wissen als> Informatiker.
Du missverstehst mich.
Ich weiss keineswegs ALLES besser als die Informatiker. Mein
Zielpunkt ist nur genau eine Sache, nämlich die didaktisch
geschickte VERMITTLUNG gewisser Teile der angewandten
Informatik.
Eingefleischte Informatiker müssen damit notwendigerweise
Probleme haben -- sie haben nämlich die Scheuklappen auf, die
ICH als Elektrotechniker in der E-Technik habe. Mir war auch
lange Zeit schleierhaft, wie man den Unterschied von Strom
und Spannung nicht kennen kann, aber ich musste mich darauf
einstellen, dass es sehr vielen Laien so geht. Arroganz hilft
da nicht weiter.
> Haben solche Ingenieure überhaupt genügend Informatik-Wissen> um darüber urteilen zu können?
Sagen wir es mal so: Da Du oben auffällig viele Sätze mit "Zwar
ist richtig, dass..." eingeleitet hast, kann die sachliche
Substanz dessen, was ich schrieb, SOOO verkehrt gar nicht
gewesen sein.
Ich stelle ja keine Behauptungen über den sachlichen Kern
der Informatik auf. Meine Aussage ist nur: Die übliche Form
der Lehre, der Darstellung lehrt meiner Meinung nach die
Dinge in einer ungünstigen Reihenfolge und mit falschen
Prioritäten.
Das ist in der Mathematik ganz genauso: Das, was als theo-
retisches Fundament der Mathematik angesehen wird, lernt man
KEINESWEGS in der 1. Klasse. Dort lernt man mathematische
Trivialitäten wie das Zahlenrechnen.
Die Grundlagen der Mathematik lernt eine winzige Minderheit
der Menschen -- nämlich im Mathematikstudium.
Jetzt ist mir noch eine Perspektive zum Thema eingefallen die vielleicht
erklärt warum es vielen möglicherweise so wie mir geht.
Konzepte wie z.B Lambda Kalkül scheint mehr ein Hochschulthema zu sein
wie frühere angewandte Problemlösung.
Wer ab den 70er Jahren mit Mikro/uC Projekten arbeiten mußte,
konzentrierte sich hauptsächlich mit den praktischen Problemen der HW/FW
Implementierung. Man dachte hauptsächlich in Logik Terminologie und
Algorithmen der Anwendung. Ich glaube nicht, daß die damaligen
Ingenieure sich viel mit Informatik Theorie befaßt haben oder mußten.
Alles drehte sich nur darum die HW zum Laufen zu bringen. Z.B ein
Entwicklungsteam bei R&S konzentrierte sich damals eben das Meßgerät
funktionsfähig zu machen.
Viele heutige Anwendungen die hauptsächlich mit Daten arbeiten, also
dort wo die unterliegende HW nur noch Mittel zum Zweck ist, dort scheint
die theoretische Informatik viel wichtiger geworden zu sein. Das sieht
man ja im gesammten Internetanwendungsbreich und Frontier Sachen wie
K.I.
Die Natur der Projekte hat sich also seit den 1970ern gewaltig geändert
und eine gewisse Perspektive ist bitter notwendig. Auch wenn
Maschinensteuerung immer noch aktuell ist, hat sich deren Verwirklichung
total gewandelt. Deshalb sehe ich auch ein, daß die modernen Anwendungen
andere Werkzeuge benötigen die eben mit den Anwendungen gewachsen sind
oder müssen.
OK. Muß jetzt weg
Gerhard
Dr. Sommer schrieb:> Wenn du mit funktionaler Programmierung anfangen> möchtest kannst du dir Sprachen wie Lisp, Scala,> Haskell, ... anschauen.
Frage am Rande: Aufgrund welcher Verschwörung fehlt
Tcl regelmäßig in solchen Aufzählungen?
(Die Frage ist völlig ernst gemeint; ich weiss viel zu
wenig von funktionaler Programmierung, um einen fundierten
Vergleich zwischen Tcl und Lisp anstellen zu könnnen.)
Possetitjel schrieb:> Sie sind deswegen furchtbar, weil die praktischen Informatiker> die Mathematik so verhuntzen. Korrigiere mich, wenn ich falsch> liege, aber eine C-function, die eine static-Variable enthält,> ist doch genau KEINE zustandsfreie Funktion mehr, oder?
Logisch. Der Begriff wird beibehalten. Es wird daher auch teilweise nach
"Prozedur" umbenannt. Funktionslokale statische nicht-konstante
Variablen sind auch so ein typisches C-Unding.
Possetitjel schrieb:> Ich habe überhaupt nichts gegen höhere Abstraktion, wenn> zuvor die einfachen, leicht zugänglichen Modelle und> Vorstellungen erklärt würden.
Ich finde OOP sehr intuitiv und verständlich. Kurioserweise haben
meistens die E-Techniker Probleme damit, obwohl da eigentlich noch mehr
in Komponenten und Black-Boxes gedacht wird (IC's, Platinen, Baugruppen,
...).
Possetitjel schrieb:> Die praktische oder angewandte Informatik IST für mich eine> Ingenieursdisziplin, genauso wie die Elektrotechnik.
Für andere aber nicht. Ich merke deutlich die Unterschiede im Denken bei
der Zusammenarbeit mit Ingenieuren.
Possetitjel schrieb:> Die übliche Form> der Lehre, der Darstellung lehrt meiner Meinung nach die> Dinge in einer ungünstigen Reihenfolge und mit falschen> Prioritäten.
Jeder lernt anders. Ich hätte mir auch eine andere Lehre gewünscht, aber
auch nicht so wie du sie dir vorstellst. Man kann es nicht jedem Recht
machen. Die sehr praktische Herangehensweise generiert schnelle
Erfolgserlebnisse, was vielen beim Lernen hilft. Auch ein Grund warum
z.B. Python viel besser für die Lehre geeignet ist als C...
Dass Theorie und Praxis weit auseinander liegen ist der typischen
akademischen Organisation geschuldet. Und das ist in der E-Technik
genauso - welcher E-Technik-Student kann einen Blinker mit NE555 bauen?
Possetitjel schrieb:> Dort lernt man mathematische> Trivialitäten wie das Zahlenrechnen.
Das ist auch das was 95% der Leute in ihrem Leben brauchen. Leider wird
Mathe immer noch als uncool angesehen, es gilt schon als chic zu sagen
"Mathe konnte ich nie". Bei Sprachen-Fächern sagt das keiner...
Wenn du in der 1. Klasse mit Definition der natürlichen, ganzen,
rationalen, irrationalen Zahlen und Körpern anfängst und dann beweist
dass R einer ist, hilft das absolut niemandem.
Possetitjel schrieb:> Frage am Rande: Aufgrund welcher Verschwörung fehlt> Tcl regelmäßig in solchen Aufzählungen?
Weil das keine besonders verbreitete Sprache ist, und funktionale
Programmierung nur ein Teilaspekt ist, im Gegensatz zu z.B. Haskell? In
C++ kann man auch funktional programmieren, insbesondere das
template-System ist quasi funktionale Programmierung.
Gerhard O. schrieb:> Ich habe mir das Wiki dazu durchgelesen. Leider verstehe ich von der> Unterliegenden Mathe zum Teil nur Bahnhof. Das ist mir zu theoretisch.
Lamdakalkül für Doofies: "Funktionen können Funktionen als Parameter
haben."
Und schon hast du die funktionale Programmierung verstanden.
Dr. Sommer schrieb:> char* greeting (const char* firstName, size_t firstNameLength, const> char* lastName, size_t lastNameLength, ) {> const char a [] = "Hallo, ";> char* res = malloc (sizeof (a) + firstNameLength + lastNameLength +> 2);> if (!res) return NULL;> memcpy (res, a, sizeof (a));> memcpy (res+sizeof (a), firstName, firstNameLength);> res [sizeof (a)+firstNameLength] = ' ';> memcpy (res+sizeof (a)+firstNameLength+1, lastName, lastNameLength);> res [sizeof (a)+firstNameLength+lastNameLength+1] = ' ';> return res;> }
Ich kenne keinen C-Programmierer, der so was schreiben würde. Auch die
Erfinder der String-Library haben sich dabei was gedacht.
Die Entsprechung zum C++-Beispiel sieht eher so aus:
Markus F. schrieb:> Die Entsprechung zum C++-Beispiel sieht eher so aus:
Funktioniert nicht mit Strings die 0-Bytes enthalten. Zugegeben, das ist
bei Real-Namen nicht besonders sinnvoll, aber es gibt oft Situationen wo
man das braucht. Besonders effizient ist das ständige Iterieren mittels
strlen auch nicht.
Dr. Sommer schrieb:> Possetitjel schrieb:>> Ich habe überhaupt nichts gegen höhere Abstraktion, wenn>> zuvor die einfachen, leicht zugänglichen Modelle und>> Vorstellungen erklärt würden.>> Ich finde OOP sehr intuitiv und verständlich.
OOP ist für mich ein einfaches und sehr sinnvolles Konzept,
das typischerweise auf eine für mich absolut unverständliche
Art erklärt wird.
Ich habe sie nur durch konsequentes Umdeuten aller Begriffe
in Kategorien der Automatentheorie verstanden, und ich werde
immer noch hippelig, wenn ich Auslassungen echter Informatiker
über OOP lesen muss. Ich kann den Frust darüber, wie man eine
einfache und sinnvolle Sache dermaßen frachtbriefmäßig
umständlich erklären kann, nur schlecht unterdrücken.
> Kurioserweise haben meistens die E-Techniker Probleme damit,> obwohl da eigentlich noch mehr in Komponenten und Black-Boxes> gedacht wird (IC's, Platinen, Baugruppen, ...).
Das ist sehr interessant, dass Du das sagst, weil ich mich in
meiner Vermutung bestätigt sehe, dass es nicht das Konzept
an sich ist, das die E-Techniker abstößt, sondern die Art und
Weise der Darstellung.
Es könnte sein, dass Wilhelm auf eine Art Recht hat, die ich
vorhin nicht gesehen habe: Möglicherweise erwerben Informatiker
trotz der Überbetonung von Sprachen und Grammatiken genügend
Wissen über Automatentheorie, so dass sich für sie die Konzepte
der OOP quasi nebenbei durch genaues Hinsehen erschließen.
E-Techniker haben diese Kenntnisse der Automatentheorie nicht
zwingenderweise; also entsteht da erstmal eine Blockade. Es
ist aber, um einigermaßen Programmieren zu können, gar nicht
notwendig, die Initiation durch TheoInf I + II über sich
ergehen zu lassen -- es genügt, den deutlich kleineren Teil
des Feldes zu beherrschen, der sich mit (endlichen) Automaten
befasst. Das wiederum sehen die Informatiker nicht, weil ihnen
mangels Notwendigkeit nicht bewusst ist, dass man Automaten-
theorie auch betreiben kann, ohne sich um die Korrespondenzen
zu den Grammatiken zu scheren.
Dr. Sommer schrieb:> Possetitjel schrieb:>> Frage am Rande: Aufgrund welcher Verschwörung fehlt>> Tcl regelmäßig in solchen Aufzählungen?>> Weil das keine besonders verbreitete Sprache ist, und> funktionale Programmierung nur ein Teilaspekt ist, im> Gegensatz zu z.B. Haskell?
Okay, das gibt Sinn. Danke.
Possetitjel schrieb:> es genügt, den deutlich kleineren Teil des Feldes zu beherrschen, der> sich mit (endlichen) Automaten befasst.
Endliche Automaten reichen da nicht, es muss mindestens bis zur Turing
Maschine gehen damit übliche Programme abbildbar werden. Und dafür
brauchts dann doch ein Semester.
Possetitjel schrieb:> dass man Automaten- theorie auch betreiben kann, ohne sich um die> Korrespondenzen zu den Grammatiken zu scheren.
Da das aber die Hauptanwendung ist gehört es irgendwie dazu.
In Anbetracht der Tatsache dass die meisten Informatiker TheoInf
überhaupt nicht verstehen aber gewöhnliches OOP mit Kapselung und
Datenstrukturen schon, würde ich nicht sagen dass es besonders hilfreich
wäre Automaten als Grundlage für alles darzustellen. Eine String Klasse
ist als Text intuitiver verstanden denn als Turing Maschine, wo auf dem
Band Zeichen, Länge usw liegen. Schlimmer wird es z.B. bei Listen oder
Graphen. Komplexe OOP-Strukturen sind da noch viel weiter entfernt...
Possetitjel schrieb:> OOP ist für mich ein einfaches und sehr sinnvolles Konzept, das> typischerweise auf eine für mich absolut unverständliche Art erklärt> wird.
Für dich mag das zutreffen, aber ich glaube nicht dass das für die
Mehrheit gilt. Das Konzept der Datenkapselung dürfte vielen besser
liegen. Insbesondere weil die meisten Informatiker Begriffe wie
Schaltwerk, Kombinatorik (in dem Zusammenhang), und 74er nie gehört
haben.
Markus F. schrieb:> Dr. Sommer schrieb:> ... Strings die 0-Bytes enthalten...>> das ist für C-Programmierer ein Oxymoron.
Dann halt Byte-Array. In den meisten Sprachen muss man sich um solche
Probleme halt keine Sorgen machen...
PS: Ich würde im Studium eher noch mehr auf die Details der
Programmiersprachen eingehen, und dafür Dinge wie Jura oder BWL
reduzieren. Wenn ich sehe was so am Code produziert wird (insbesondere
in C und C++) überkommt einen das Gruseln. In C sind viele Dinge einfach
falsch und werden trotzdem wie selbstverständlich überall so gemacht...
Hallo,
Dr. Sommer schrieb:> PS: Ich würde im Studium eher noch mehr auf die Details der> Programmiersprachen eingehen...
Was meinst du mit "Details"?
rhf
Possetitjel schrieb:> Es könnte sein, dass Wilhelm auf eine Art Recht hat, die ich> vorhin nicht gesehen habe: Möglicherweise erwerben Informatiker> trotz der Überbetonung von Sprachen und Grammatiken genügend> Wissen über Automatentheorie, so dass sich für sie die Konzepte> der OOP quasi nebenbei durch genaues Hinsehen erschließen.
Das ist komplett daneben. Ich habe fast zehn Jahre vor dem Studium mit
dem Programmieren angefangen, direkt mit C# und OOP. Gerade Java und C#
erzwingen OOP ja extrem. Da hatte ich keine Ahnung von Automatentheorie
oder Ähnliches. Und trotzdem haben sich mir diese Konzepte erschlossen.
Und ich war da nicht der Einzige, ein paar Jungs aus der Computer-AG
haben das auch verstanden. Es ist einfach nicht nötig. Das Buch, dass
ich damals verwendete, nutze die Analogie eines Autos oder eines
Bauernhofes, bin mir nicht mehr so sicher. Auf jeden Fall so, dass es
ein 0815 Mensch ohne jegliche Vorkenntnisse verstehen kann. Andererseits
ist es im Studium auch so, dass viele im ersten Semester direkt mit Java
anfangen, Theoretische Informatik kommt hingegen erst später.
Possetitjel schrieb:> Ich habe sie nur durch konsequentes Umdeuten aller Begriffe> in Kategorien der Automatentheorie verstanden, und ich werde> immer noch hippelig, wenn ich Auslassungen echter Informatiker> über OOP lesen muss. Ich kann den Frust darüber, wie man eine> einfache und sinnvolle Sache dermaßen frachtbriefmäßig> umständlich erklären kann, nur schlecht unterdrücken.
Genau das ist eben dein Problem, Umdeuten ist halt nicht Verstehen. Du
bist von der Automathentheorie zu sehr vereinnahmt, weshalb du den
Sachverhalt nicht mehr anders betrachten kannst. Die Betrachtungsweise
musst du fallen lassen. Deswegen auch die Abneigung gegenüber der
Vererbung, die aber ein essentieller Teil von OOP ist, weil sie mit
"deiner Betrachtungsweise" nicht harmoniert.
Niklas Gürtler schrieb:> Possetitjel schrieb:>> es genügt, den deutlich kleineren Teil des Feldes zu>> beherrschen, der sich mit (endlichen) Automaten befasst.>> Endliche Automaten reichen da nicht, es muss mindestens> bis zur Turing Maschine gehen damit übliche Programme> abbildbar werden.
Es ging um die Frage, warum viele E-Techniker mit OOP
solche Probleme haben.
Um die Grundidee der OOP zu erklären, muss ich nicht
bis zur Turingmaschine gehen -- das habe ich nämlich
in meinem ersten, überlangen Beitrag schon getan.
> Possetitjel schrieb:>> dass man Automatentheorie auch betreiben kann, ohne>> sich um die Korrespondenzen zu den Grammatiken zu>> scheren.>> Da das aber die Hauptanwendung ist gehört es irgendwie> dazu.
Kein Zweifel: Hier spricht ein Informatiker.
Für mich liegt die Domäne der Automatentheorie in allen
Arten von Prozess- und Ablaufsteuerungen. Die Korrespondenz
zu den Grammatiken ist für mich ein winziges Spezialthema,
das nur für die theoretischen Informatiker wichtig ist.
Ich schreibe das nicht als Provokation, sondern weil es
die Wahrheit ist.
Ich hatte eine kleine Weile Berührung mit Steuerungs-
programmierung (SPS), und ich wäre völlig erschossen gewesen,
wenn ich nichts von endlichen Automaten gewusst hätte.
> In Anbetracht der Tatsache dass die meisten Informatiker> TheoInf überhaupt nicht verstehen aber gewöhnliches OOP> mit Kapselung und Datenstrukturen schon, würde ich nicht> sagen dass es besonders hilfreich wäre Automaten als> Grundlage für alles darzustellen.
Das beweist erstmal nur, dass die Art und Weise der
Darstellung von TheoInf schlecht ist.
> Eine String Klasse ist als Text intuitiver verstanden> denn als Turing Maschine, wo auf dem Band Zeichen, Länge> usw liegen.
Wenn ich "Automatentheorie" sage, dann denke ich primär
an ENDLICHE Automaten.
> Possetitjel schrieb:>> OOP ist für mich ein einfaches und sehr sinnvolles Konzept,>> das typischerweise auf eine für mich absolut unverständliche>> Art erklärt wird.>> Für dich mag das zutreffen, aber ich glaube nicht dass das> für die Mehrheit gilt. Das Konzept der Datenkapselung dürfte> vielen besser liegen.
Ein "Objekt" IST ein (häufig endlicher) Automat.
> Insbesondere weil die meisten Informatiker Begriffe wie> Schaltwerk, Kombinatorik (in dem Zusammenhang), und 74er> nie gehört haben.
Das ist ja der Skandal!
Mist... überlesen:
Dr. Sommer schrieb:> Possetitjel schrieb:>> Die praktische oder angewandte Informatik IST für mich>> eine Ingenieursdisziplin, genauso wie die Elektrotechnik.>> Für andere aber nicht. Ich merke deutlich die Unterschiede> im Denken bei der Zusammenarbeit mit Ingenieuren.
Nur interessehalber: Welche sind das? Bzw. wie zeigen sie
sich?
Possetitjel schrieb:> Carl D. schrieb:>>> Manchmal kann der Erkenntnisstand der "Pioniere" aber>> nicht auf Nachzügler warten.>> Es geht nicht um den Erkenntnisstand an sich, sondern> um die Unfähigkeit oder die Unlust, die unter vielen> persönlichen Mühen gewonnenen Erkenntnisse so umzuformu-> lieren, dass sie für andere leicht verständlich werden.>> Edison sage, Genie sei 1% Inspiration und 99% Transpiration.>> Die geniale Erkenntnis zu haben ist 1%, sie verständlich> zu formulieren und lehrbar zu machen, die restlichen 99%.
Aha, und worin leitet sich der Anspruch derer ab, die sich gedanklich
auf das Vorgestellte nicht selber einlassen wollen, die Erkenntnisse
mundgerecht vorgelegt zu bekommen?
@Possetitjel:
Ich habe mir die Mühe gemacht, deinen ellenlangen Beitrag von oben
durchzulesen, jetzt musst du dasselbe auch mit meinem tun ;-)
Alle anderen dürfen ihn gerne überspringen.
Wenn ich dich richtig verstehe, versucht du, sämtliche Eigenschaften von
Programmiersprachen auf Automaten abzubilden, um sie dadurch besser zu
verstehen. Kann es sein, dass du dich damit selber blockierst und so
somit genau das Gegenteil von dem erreichst, was du eigentlich
anstrebst?
Was du in deinen Beispielen mittels Automaten beschreibst, sind im
Wesentlichen Ablaufstrukturen (Sprünge, Unterprogrammaufrufe, Objekte
mit Memberfunktionen, Parallelität usw.). Im Gegensatz zu Assembler und
Ur-Fortran zeichnen sich moderne Sprachen aber durch weit mehr als nur
die von ihnen unterstützten Ablaufstrukturen aus, als da wären:
- Datentypen (numerisch, textuell, primitiv, zusammengesetzt, ...)
- Typsysteme (stark, schwach, statisch, dynamisch, flach, hierarchisch,
...)
- Möglichkeiten der Metaprogrammierung (Lisp-Makros, C++-Templates, ...)
- u.v.m.
Ich bin zwar Informatiker, beschäftige mich aber auch mit Elektronik und
sonstiger Technik. Deswegen versuche auch ich, meinem Verständnis
abstrakter Sachverhalte dadurch auf die Sprünge zu helfen, dass ich in
meiner Vorstellung kleine Maschinchen baue, die mit irgendetwas (wie
bspw. Daten, Programmcode, geometrische Objekte oder was auch immer)
gefüttert werden und daraus – entweder einmalig oder laufend wie am
Fließband – unter heftiger (vorgestellter) Geräuschentwicklung
irgendetwas anderes erzeugen.
Das funktioniert für viele Dinge (wie bspw. eine Programmschleife, einen
Stack und sogar die Synchronisation zwischen mehreren Prozessen) ganz
hervorragend, aber bei den in der obigen Aufzählung genannten Punkten
ist meine Phantasie nicht mehr in der Lage, solche Maschinchen zu
konstruieren. Für einige Dinge (wie bspw. Mehrfachrekursion) kann ich
zwar ein entsprechendes Maschinchen bauen, aber bei der Inbetriebnahme
verklemmt es sich oder zerfällt sogar in seine Einzelteile, weil meine
Vorstellungskraft für das Durchspielen der Bewegungsabläufe nicht
ausreicht.
Ich habe deswegen lange nach einem besseren Ersatz für diese Maschinchen
gesucht und schließlich auch gefunden:
Mathematische Modelle
Diejenigen, die schon lange vor mir auf diese Idee kamen, habe ich
früher immer als unverbesserliche Theoretiker angesehen und ihre
unverständlichen Aussagen als Geschwurbel abgetan.
Der Punkt bei der Sache: Ich musste anhand einiger konkreter Probleme
erst einmal selber auf den Dreh kommen, um zu glauben, dass da etwas
dran ist. Danach hat plötzlich auch das Geschwurbel der anderen (naja,
vieler, nicht aller ;-)) für mich eine Bedeutung bekommen.
Endgültig die Augen aufgegangen sind mir, als ich begann, mich mit
funktionaler Programmierung zu beschäftigen. In der reinen FP gibt es
weder Abläufe noch Zustände, weswegen die Vorstellung von Maschinchen
schon per se zu nichts führen kann.
Mit mathematische Modellen hingegen kann man einige Dinge tun, die mit
den Maschinchen in meinem Kopf kaum möglich sind:
- Man kann sie leicht zu Papier bringen und damit komplizierte
Gedankengänge auch außerhalb des Kopfs speichern.
- Man kann damit Beweise führen und sich so selber klar machen, das ein
komplizierter Algorithmus, den man gerade geschrieben hat, auch
wirklich in allen Kontexten das richtige Ergebnis liefert.
- Man kann sie transformieren. Eine praktische Anwendung davon ist es,
Programmcode so umzuschreiben, dass er effizienter wird, ohne dabei
Fehler einzubauen. Die Vorgehensweise ist letztendlich nichts anderes
als geschickte Umformen mathematischer Terme. Konkrete Beispiele
finden sich bspw. in dem Buch "Pearls of Functional Algorithm Design"
von Richard Bird.
Immer wieder fallen mir bei schwierigen Problemen weitere Wege ein, die
zwar abstrakt anmuten, aber letztendlich dazu geeignet sind, hinderliche
Knoten in Gehirnwindungen zu lösen und damit die Problemstellung zu
vereinfachen.
Und das Beste dabei: Die Erkenntnisse, die man dabei gewinnt, lassen
sich nicht nur auf die FP, sondern mit leichten Einschränkungen auch auf
die klassische Programmierung in C oder C++ anwenden.
Was ich damit ausdrücken möchte: Die Informatiker, deren Geschwurbel du
nicht verstehst, sind entweder tatsächlich Dummschwätzer oder Angeber,
oder aber sie denken in Modellen, die sie persönlich zwar befähigen,
selbst schwierigste Probleme zu lösen, die sich aber leider nicht in
deine Welt der Automaten übersetzen lassen. Umgekehrt haben diese Leute
vielleicht (wenn sie sich nie damit beschäftigt haben) Schwierigkeiten
damit, sich ein zeitlich veränderliches Signal im Frequenzbereich
vorzustellen, was für einen Elektroingenieur nichts besonders ist.
Carl D. schrieb:> Possetitjel schrieb:>> Carl D. schrieb:>>>>> Manchmal kann der Erkenntnisstand der "Pioniere" aber>>> nicht auf Nachzügler warten.>>>> Es geht nicht um den Erkenntnisstand an sich, sondern>> um die Unfähigkeit oder die Unlust, die unter vielen>> persönlichen Mühen gewonnenen Erkenntnisse so umzuformu->> lieren, dass sie für andere leicht verständlich werden.>>>> Edison sage, Genie sei 1% Inspiration und 99% Transpiration.>>>> Die geniale Erkenntnis zu haben ist 1%, sie verständlich>> zu formulieren und lehrbar zu machen, die restlichen 99%.>> Aha, und worin leitet sich der Anspruch derer ab, die sich> gedanklich auf das Vorgestellte nicht selber einlassen> wollen, die Erkenntnisse mundgerecht vorgelegt zu bekommen?
Auch wenn das wenig bis nichts mit Wilhelm zu tun hat:
Der Anspruch leitet sich schlicht aus der normativen Kraft
des Faktischen ab: Wenn ich die Wahl zwischen einem
unverständlichen und einem klar verständlichen Buch habe,
dann wähle ich ganz sicher nicht das unverständliche. Eins
meiner wenigen Privilegien besteht darin, mir meine Lehrer
aussuchen zu können.
Es interessiert mich keinen Deut, wenn der Autor des ersten
ein verkanntes Genie, der Autor des zweiten Buches aber nur
gutes Mittelmaß ist.
Wer sich zu fein ist, Arbeit in verständliche Darstellung zu
stecken, der bleibt am Ende eben auch genau das: Unverstanden.
Das ist sein Problem, nicht meins.
Possetitjel schrieb:> Carl D. schrieb:>>> Possetitjel schrieb:>>> Carl D. schrieb:>>>>>>> Manchmal kann der Erkenntnisstand der "Pioniere" aber>>>> nicht auf Nachzügler warten.>>>>>> Es geht nicht um den Erkenntnisstand an sich, sondern>>> um die Unfähigkeit oder die Unlust, die unter vielen>>> persönlichen Mühen gewonnenen Erkenntnisse so umzuformu->>> lieren, dass sie für andere leicht verständlich werden.>>>>>> Edison sage, Genie sei 1% Inspiration und 99% Transpiration.>>>>>> Die geniale Erkenntnis zu haben ist 1%, sie verständlich>>> zu formulieren und lehrbar zu machen, die restlichen 99%.>>>> Aha, und worin leitet sich der Anspruch derer ab, die sich>> gedanklich auf das Vorgestellte nicht selber einlassen>> wollen, die Erkenntnisse mundgerecht vorgelegt zu bekommen?>> Auch wenn das wenig bis nichts mit Wilhelm zu tun hat:>> Der Anspruch leitet sich schlicht aus der normativen Kraft> des Faktischen ab: Wenn ich die Wahl zwischen einem> unverständlichen und einem klar verständlichen Buch habe,> dann wähle ich ganz sicher nicht das unverständliche. Eins> meiner wenigen Privilegien besteht darin, mir meine Lehrer> aussuchen zu können.>> Es interessiert mich keinen Deut, wenn der Autor des ersten> ein verkanntes Genie, der Autor des zweiten Buches aber nur> gutes Mittelmaß ist.
Warum liest und kommentierst du dann das erste Buch?
> Wer sich zu fein ist, Arbeit in verständliche Darstellung zu> stecken, der bleibt am Ende eben auch genau das: Unverstanden.
Richtig, von manchen unverstanden.
Und nochmal, es gibt keinen Anspruch auf Erkenntnis und schon gar nicht
in der Passivform.
> Das ist sein Problem, nicht meins.
Dann Versuch doch nicht, ihm das wegzunehmen.
Yalu X. schrieb:>> Ich habe mir die Mühe gemacht, [.]einen ellenlangen Beitrag von oben> durchzulesen ..>> Alle anderen dürfen ihn gerne überspringen.
Falls es dich interessiert, ich habe bei dir nicht das Gefühl "irgendein
Geschwurbel" zu lesen im Gegensatz zu manch anderen Texten hier, die mir
reichlich wirr und ohne erkennbaren Faden erscheinen. Ich frage mich nur
gerade angesichts vieler alltäglicher Programmieraufgaben, welche
speziellen Applikationen es denn überhaupt notwendig machen den Pfad des
"normalen", intuitiven Lösungsansatzes zu verlassen, um sich einer
völlig anderen Herangehensweise bedienen zu müssen?
Ach ja ;) schrieb:> Ich frage mich nur> gerade angesichts vieler alltäglicher Programmieraufgaben, welche> speziellen Applikationen es denn überhaupt notwendig machen den Pfad des> "normalen", intuitiven Lösungsansatzes zu verlassen, um sich einer> völlig anderen Herangehensweise bedienen zu müssen?
Jetzt wage ich mich nochmals aufs Eis:
Ich stelle mir vor, daß im herkömmlichen Feld der Hardware intensiven
Steueraufgaben traditionelle Methoden immer noch sinnreich und
vernünftig sind weil man tonnenweise eine wiederverwendbare, verläßliche
und bewährte Codebasis hat.
Es sind eher die modernen Applikation wie IoT, Internet verbundener
Sachen die sehr Daten intensiv und von Protokollen abhängig sind und
viel kommunizieren wo die neuen Werkzeuge dem Designer das Leben
leichter machen. Es gibt ja heute so viele Aufgaben die aus 90% GUI und
Communication und der Rest bestehen und irgendwelche einfache Steuer-
und Meßaufgaben abarbeiten. Da sehe ich zumindest die Vorteile und man
sollte sie nützen sofern man es kann:-)
Als eingefleischter Praktiker tue ich mir im Augenblick schwer mich mit
der neuen Materie vertraut zu machen. Aber vielleicht klappt es allen
anfänglichen Schwierigkeiten zum Trotz doch einmal.
Abgesehen davon hängt Vieles davon ab welche Entwicklungswerkzeuge und
uC Ressourcen vorhanden sind. Viele der neuen Tols benötigen eher
großzügige Ressourcen und sind auf kleinen uC eher mißplaziert.
Wie Arduino beweist ist der Gebrauch eines Subsets von C++ durchaus
realistisch und würde persönlich mehr Zeit und Muße dort reinstecken
wollen um zumindest auf dieser Ebene etwas kompetenter zu sein.
Die Experten auf diesen Gebiet wissen sowieso wie sie ihre
Projektprobleme lösen wollen und können und brauchen keine
Besserwisser:-)
Ok. Das wärs so ziemlich für mich was dieses Thema angeht. Ich brauche
mir nicht meine Brötchen damit zu verdienen und kann mir aussuchen was
ich noch lernen will. Vielleicht fällt doch irgendwann der Groschen. Ich
werde sicherlich verfolgen was auf diesem Gebiet noch erörtert wird.
Tut mir leid wenn ich Euch mit meinen Betrachtungen und Meinungen zu
Tode gelangweilt habe. Mir war es nur wichtig mal die andere Seite
aufzuzeigen.
Schönes Wochenende noch,
Gerhard
Ach ja ;) schrieb:> Yalu X. schrieb:>>>> Ich habe mir die Mühe gemacht, [.]einen ellenlangen Beitrag von oben>> durchzulesen ..>>>> Alle anderen dürfen ihn gerne überspringen.>> Falls es dich interessiert, ich habe bei dir nicht das Gefühl "irgendein> Geschwurbel" zu lesen im Gegensatz zu manch anderen Texten hier, die mir> reichlich wirr und ohne erkennbaren Faden erscheinen. Ich frage mich nur> gerade angesichts vieler alltäglicher Programmieraufgaben, welche> speziellen Applikationen es denn überhaupt notwendig machen den Pfad des> "normalen", intuitiven Lösungsansatzes zu verlassen, um sich einer> völlig anderen Herangehensweise bedienen zu müssen?
Weil mal das eine Paradigma Vorteile gegenüber andere in gewissen
Situationen bietet. Vor allem, was soll denn dieser "normale intuitiver
Lösungsansatz" sein? Ist das frei nach dem Moto "wer nur einen Hammer
kennt, sieht in jedem Problem nur einen Nagel"? Es gibt auch in diesem
Fall nicht diesen einen intuitiven Lösungsansatz. Jeder scheint darunter
auch etwas anderes zu verstehen, für den einen ist die
Metaprogrammierung in C++ absolut schlüssig und vorteilhaft, der andere
verabscheut gleich " aufgeblassene, bürokratische" Hochsprachen und
nimmt immer Assembler...
Oh, die Diskussion ist ja ganz woanders ...
Possetitjel schrieb:> Auch wenn das wenig bis nichts mit Wilhelm zu tun hat:>> Der Anspruch leitet sich schlicht aus der normativen Kraft> des Faktischen ab: Wenn ich die Wahl zwischen einem> unverständlichen und einem klar verständlichen Buch habe,> dann wähle ich ganz sicher nicht das unverständliche. Eins> meiner wenigen Privilegien besteht darin, mir meine Lehrer> aussuchen zu können.
Ich verstehe dieses Forum immer noch als Hilfe zur Selbsthilfe und ich
habe nicht den Anspruch hier Kapitel eines Lehrbuches abzuliefern oder
alles vorzuverdauen. Es geht mir nur um Anregungen. Wer nicht die
Vorstellungskraft hat, dahinter einen Wert zu erkennen, der ihn dazu
bringt, sich selbst(!) damit zu beschäftigen, der soll es eben sein
lassen. Wer also ein Motiv hat, kann ja fragen. Ich bin kein
Motivationstrainer sondern gehe von instrinsischer Motivation aus.
Gerade in diesem Forum!
Und alles auf einen Automaten zurückzuführen finde ich ähnlich
abenteuerlich wie das oben Yalu geschrieben hat. Ich finde die Modelle
und Werkzeuge der theoretischen Informatik sehr nützlich, vor allem,
weil man es mit Papier und Bleistift erledigen kann, allerdings kann ich
auch verstehen, dass hier ggf. das Abstraktionsvermögen anderer aufhört.
Gerhard O. schrieb:> Als eingefleischter Praktiker tue ich mir im Augenblick schwer mich mit> der neuen Materie vertraut zu machen. Aber vielleicht klappt es allen> anfänglichen Schwierigkeiten zum Trotz doch einmal.
Aus meiner Sicht sollte man sich die folgenden Fragen (ausgehend von
einer C-Welt) stellen:
* wann kann/soll der Berechnungszeitpunkt sein: Compilezeit,
Auführungszeit
* kann ich das Typsystem der Sprache modifizieren: ja/halb/nein
* wie/wann kann ich das Typsystem modifizieren: statisch im Quelltext,
durch Berechnung zur Compilzeit, zur Laufzeit
Das Typsystem ist deswegen so wichtig, weil es der Kern der
imperativ/prozeduralen Sprachen wie C oder C++ (hat noch mehr
Paradigmen) ist.
In C kann ich keine Berechnungen zur Compilezeit machen und ich kann nur
das eingebaute Typsystem verwenden. Somit ist es sehr schwer,
abstrakteren Code zu schreiben. Je komplizierter die Aufgabe, desto mehr
Abstraktion ist notwendig, um das Problem beherrschen zu können.
In C++ kann man:
* Berechnungen zur Compilezeit durchführen: der Compiler "interpretiert"
den Code im Moment des Compilierens
* das Typsystem modifizieren, etwa einen Datentyp erfinden, der beim
inkrementieren bei bspw. 10 saturiert oder zirkulär die Werte 0...9
annimmt. Oder einen Datentyp String, der von der C-orientieren
Sichtweise einzelner Zeichen abstrahiert, die es erlaubt, Strings zu
addieren/konkatenieren (+) oder lexikografisch zu vergleichen (<).
* die Modifikation des Typsystems kann im Quelltext statisch stattfinden
(Klassen erstellen) oder zur Compilezeit "berechnet" werden. Wenn es
bspw. bekannt ist, dass ein Array maximal 100 Elemente enthält, reicht
als DT für den Index ein uint8_t aus, es muss kein size_t sein. Das kann
der Compiler zur Compilezeit selbst ermitteln.
Dies sind ein paar Dinge, die das Abstraktionsniveau erhöhen und damit
Fehler vermeiden helfen, z.B. unerwünschter Wrap-around bei zu kleinen
Ganzzahltypen, und die erstmal mit OOP in engeren Sinne, also
Laufzeitpolymorphie (Liskov) gar nichts zu tun haben.
> Ok. Das wärs so ziemlich für mich was dieses Thema angeht.
Vielleicht sind die o.g. Dinge eine kleine Motivation, etwas tiefer
einzusteigen.
Wilhelm M. schrieb:> Vielleicht sind die o.g. Dinge eine kleine Motivation, etwas tiefer> einzusteigen
Wilhelm,
Ist es schon und bedanke mich auch für Deine Hinweise.
Aber der Appettit kommt mit dem Essen und es ist notwendig eine
Entwicklungsumgebung zu installieren die das auch kann. Ich kann nur
lernen wenn ich mich damit praktisch befassen kann. Nur darüber zu lesen
ist zwecklos für mich.
Ich hatte vergessen zu fragen ob es Sinn hätte am PC mit Visual Studio
zuarbeiten. Das dürfte so ziemlich uptodate sein. Zum Lernen wäre das
ideal weil es in Windows lauffähig sein müßte.
Den CYgwin GCC compiler wollte ich installieren, hatte aber Internet
Verbindungsprobleme und das Installierprogramm gab auf. Da müßte ich mal
rausfinden warum das nicht geht.
Also halte mir den Daumen,
Gerhard
Gerhard O. schrieb:> Ich hatte vergessen zu fragen ob es Sinn hätte am PC mit Visual Studio> zuarbeiten. Das dürfte so ziemlich uptodate sein. Zum Lernen wäre das> ideal weil es in Windows lauffähig sein müßte.
Natürlich, man lernt auf dem PC, und MSVS ist ok, wenn es recht aktuell
ist.
> Also halte mir den Daumen,> Gerhard
Klaro - und bei Fragen ... fragen
Wilhelm M. schrieb:> Gerhard O. schrieb:>>> Ich hatte vergessen zu fragen ob es Sinn hätte am PC mit Visual Studio>> zuarbeiten. Das dürfte so ziemlich uptodate sein. Zum Lernen wäre das>> ideal weil es in Windows lauffähig sein müßte.>> Natürlich, man lernt auf dem PC, und MSVS ist ok, wenn es recht aktuell> ist.>>> Also halte mir den Daumen,>> Gerhard>> Klaro - und bei Fragen ... fragen
Ok. Danke. Werde Dich beim Wort nehmen:-)
Im vorherigen Beitrag beschriebst Du die Compile Möglichkeiten. Das hört
sich toll an obwohl ich mir im Augenblick noch wenig darunter vorstellen
kann wie das im Einzeln vor sich geht. Deshalb wäre Experimentation
wahrscheinlich der beste Weg um dafür ein praktisches Gefühl dafür zu
bekommen.
Soweit es uC angeht wäre wahrscheinlich Atollic die einzige Umgebung wo
das vielleicht auch mit uC wie STM32 Typen funktioniert. Da müßte man
mal recherchieren inwieweit deren GCC Compiler uptodate ist.
PC Apps programmieren tue ich eigentlich sonst nicht.
Gerhard O. schrieb:> Soweit es uC angeht wäre wahrscheinlich Atollic die einzige Umgebung wo> das vielleicht auch mit uC wie STM32 Typen funktioniert. Da müßte man> mal recherchieren inwieweit deren GCC Compiler uptodate ist.
GCC für ARM hat auch ein libstdc++.
Aber das Testen Deiner Programme ist doch auf dem PC in einer IDE viel
einfacher. Später machst Du den Übergang zu µC.
TriHexagon schrieb:> was soll denn dieser "normale intuitiver> Lösungsansatz" sein?
Wie ja jeder weiß, entsteht Software stets ingenieursmäßig durch
ausgefuchstes, intensives Modellieren streng nach Entwicklungsplan, wie
aus dem Lehrbuch und jeder der auch nur eine Zeile Code schreibt, bevor
nicht auch der letzte Detailentwurf ausgearbeitet und auf Folie
präsentiert ist, der ist ein ganz, ganz schlimmer Mensch. :)
Oder vielleicht eher doch nicht?
Das wäre dann der erwähnte eher intuitive Lösungsansatz. Soll heißen,
natürlich schon ein paar Gedanken machen wo es hingehen soll, aber dann
auch zügig anfangen zu Programmieren, um schnell erste Ergebnisse zu
haben.
Wie jeder persönlich da vorgeht (oder vorgehen muss, weil's der
Arbeitgeber bestimmt) und welcher Mittel er sich dabei bedient muss
natürlich jeder für sich selber entscheiden. Yalu beispielsweise baut
sich gedanklich seine kleinen Maschinchen, die er anschließend mit Daten
füttert, in der Hoffnung, dass hinterher auch das "richtige" bei
rauskommt. Inzwischen hat er diesen Ansatz aber wohl hinter sich
gelassen.
Gerhard greift auf den Fundus seiner wiederverwendbaren und
verlässlichen Codebasis zurück. Dr. Sommer wird seinen C++ -Kasten in
Schwung bringen. Von einem hier in Forum las ich mal Nim hätte es ihm
angetan. Der Admin (Schwarz) schwört wohl auf Python und Ruby (las ich
mal). Es soll auch manche hier geben, die ihr Glück in einem
Bezahl-BASIC gefunden haben. Mein Eindruck ist jeder ist da seinen
Gewohnheiten irgendwie erlegen und nimmt halt das was er beherrscht. Was
natürlich niemandem daran hindert auch neue Pfade auszuprobieren.
Was den Hammer betrifft, eine Software ist nicht ein simples
Metall-Hau-Werkzeug, dass jeder in schneller Anlernmanier mal eben
austauschen kann. Eine lieb gewonnene Radfahr-Gewohnheit auf dem eigenen
Rennrad lässt sich auch nicht so einfach gegen die auf einem (fremden)
Tandem eintauschen. Das ist nun mal nicht das gleiche bzw. fühlt sich
völlig anders an. Genau so sieht es auch mit einer langjährig eingeübten
Programmiersprache oder einem Programmier-Paradigma wie OOP vs.
Prozedurales Programmieren aus. So ein Wechsel ist nicht mal eben auf
die Schnelle gemacht. Nicht wenige scheitern ja schon am Eingewöhnen an
FreeCAD oder an den MS Office Ribbons ;-) oder wie ich letztens las
proggen lieber auf der Linux Kommandozeile in C, weil's so schön einfach
geht anstatt sich mit der aufgeblasenen MS Visual C++ IDE
herumzuschlagen. :)
Es kommt hinzu, mit zunehmendem Alter nimmt die einstige studentische
Ausprobier-Euphorie auch eher steil ab. Da ist der Alltag einfach anders
(straffer) strukturiert und die Zeit für viel Experimentierfreude nicht
mehr so vorhanden. Also nimmt man was man kennt und gut ist.
:)
Wilhelm M. schrieb:> Gerhard O. schrieb:>>> Soweit es uC angeht wäre wahrscheinlich Atollic die einzige Umgebung wo>> das vielleicht auch mit uC wie STM32 Typen funktioniert. Da müßte man>> mal recherchieren inwieweit deren GCC Compiler uptodate ist.>> GCC für ARM hat auch ein libstdc++.> Aber das Testen Deiner Programme ist doch auf dem PC in einer IDE viel> einfacher. Später machst Du den Übergang zu µC.
Das stimmt und hatte ich sowieso vor. Bevor ich nicht ein gewisses Maß
Selbstvertrauen diesbezüglich erworben habe, hätte es wenig Sinn auf dem
uC zu experimentieren.
Naja. Vielleicht wird es besser gehen wie ich mir es ausmale. Allerdings
wird ein Teil der Bemühungen Eine Dokubasis zum Nachschlagen aufzubauen
da ich zur Zeit noch nichts habe.
Wie ist eigentlich z.B mit der Stringdoku?
Wenn ich jetzt eine String search machen wollte, geht das mit
trickreicher Operator Magie oder Funktionsaufruf alleine? Das sind so
die Fragen die ich mir beantworten muß. Auch wie ein Minimal Program
aufgebaut sein müßte und die notwendigen Header Files. Da habe ich noch
einiges vor mir. Naja, Dein Beispielprogram vorher, gibt mir da schon
einen Start.
Laßt Euch von mir überraschen...
Ach ja ;) schrieb:> Oder vielleicht eher doch nicht?
Ich bin ein ganz schlimmer Mensch:-)
Da ich meist meine eigene HW entwickle denke ich auch schon parallel mit
wie die HW Gestaltung Aspekte die zukünftige SW beeinflussen würde um
unnötige SW Klimmzüge zu vermeiden. Dann, wenn die HW existiert teste
ich alles durch und schreibe und teste mal zuerst die Treiber oder
verwende schon vorhandene Treiber von vorherigen Projekten, so daß man
die Peripherie ansprechen kann. Dafür habe ich mir ein Standard Test
Program geschneidert mit dem ich meine HW dann virtualisieren kann und
testen. Da habe ich dann sofort Zugang auf die meisten Peripherien des
uC, extern oder intern.
Die eigentliche SW wird erst dann wirklich geplant und detailliert. Da
man zu diesem Zeitpunkt weiß was HW mäßig funktioniert oder nicht, macht
dann die spätere Arbeit viel weniger nervig.
Carl D. schrieb:>> Es interessiert mich keinen Deut, wenn der Autor des>> ersten ein verkanntes Genie, der Autor des zweiten>> Buches aber nur gutes Mittelmaß ist.>> Warum liest und kommentierst du dann das erste Buch?
Das tue ich nicht.
Ich habe DIR geantwortet, nicht Wilhelm oder sonstwem.
Es war DEINE elitäre Behauptung, die "Pioniere" könnten
nicht auf jeden Nachzügler warten.
Meine Antwort DARAUF ist: Wenn sich die "Pioniere" zu
fein sind, sich allgemeinverständlich auszudrücken,
sollen sie nicht rumheulen, dass man sie nicht versteht.
Ursache -- Wirkung. Kausalität.
Mit Wilhelm hat das nix zu tun. Mich nerven Deine elitären
Unterstellungen.
Wilhelm M. schrieb:> Possetitjel schrieb:>> Auch wenn das wenig bis nichts mit Wilhelm zu tun hat:>>>> Der Anspruch leitet sich schlicht aus der normativen Kraft>> des Faktischen ab: Wenn ich die Wahl zwischen einem>> unverständlichen und einem klar verständlichen Buch habe,>> dann wähle ich ganz sicher nicht das unverständliche. Eins>> meiner wenigen Privilegien besteht darin, mir meine Lehrer>> aussuchen zu können.>> Ich verstehe dieses Forum immer noch als Hilfe zur Selbsthilfe
Du hast aber schon gelesen, dass ich den Abschnitt überschrieben
habe mit "Auch wenn das wenig bis nichts mit Wilhelm zu tun hat"?
> und ich habe nicht den Anspruch hier Kapitel eines Lehrbuches> abzuliefern oder alles vorzuverdauen. Es geht mir nur um> Anregungen.
Das verstehe ich.
Eine Anregung hat ja aber den Sinn, Lust auf mehr zu machen.
Das erreichen Deine Anregungen aber bei mir nicht, sie
schrecken mich eher ab.
Der Grund dafür liegt darin, dass Deine Anregungen zu wenig
an das anknüpfen, was ich kenne.
Das kannst Du natürlich als Unverschämtheit und als Anspruchs-
haltung interpretieren -- aber es ist erstmal nur eine sachliche
Aussage. Was Du damit anfängst, ist Deine Sache.
> Und alles auf einen Automaten zurückzuführen finde ich> ähnlich abenteuerlich wie das oben Yalu geschrieben hat.
Steht Dir völlig frei.
Im Gegensatz zu Dir formuliert Yalu seine Zweifel und Fragen
an mich ausführlich und gibt mir die Chance, mich zu erklären.
> Ich finde die Modelle und Werkzeuge der theoretischen> Informatik sehr nützlich,
Ich auch.
Zu den Modellen und Werkzeugen der theoretischen Informatik
gehören allerdings auch die Automaten. Insofern verstehe ich
Deine Bemerkung von oben nicht. Immerhin ist die Turing-Maschine
auch ein Automat.
Ich habe auch nirgendwo gegen die theoretische Informatik
polemisiert. Meine Aussage war nur, dass die Bücher über
PROGRAMMIERSPRACHEN, die ich kenne, Scheisse sind, weil sie
sich in Details verlieren, die die Konzepte eher verdecken
als erklären. Das hat wenig bis nichts mit theoretischer
Informatik zu tun.
> vor allem, weil man es mit Papier und Bleistift erledigen> kann, allerdings kann ich auch verstehen, dass hier ggf.> das Abstraktionsvermögen anderer aufhört.
???
Ich pflege die Automatentheorie, die ich brauche, fast immer
mit Papier und Bleistift zu erledigen.
Und woher weisst Du, wo mein Abstraktionsvermögen endet?
Possetitjel schrieb:> Carl D. schrieb:>>>> Es interessiert mich keinen Deut, wenn der Autor des>>> ersten ein verkanntes Genie, der Autor des zweiten>>> Buches aber nur gutes Mittelmaß ist.>>>> Warum liest und kommentierst du dann das erste Buch?>> Das tue ich nicht.>> Ich habe DIR geantwortet, nicht Wilhelm oder sonstwem.> Es war DEINE elitäre Behauptung, die "Pioniere" könnten> nicht auf jeden Nachzügler warten.
Den Begriff "Pionier" haben ich als leicht überzeichneten Gegensatz zu
den "was wir immer gemacht haben, hat uns immer gereicht"-Schreibern
gewählt. Ich hab nichts gegen diese, möchte mich im Gegenzug von ihnen
aber auch nicht bremsen lassen.
> Meine Antwort DARAUF ist: Wenn sich die "Pioniere" zu> fein sind, sich allgemeinverständlich auszudrücken,> sollen sie nicht rumheulen, dass man sie nicht versteht.> Ursache -- Wirkung. Kausalität.
Sie sind "sich zu fein" auch denen, denen die Happen warum auch immer zu
groß sind, diese vorzukauen.
> Mit Wilhelm hat das nix zu tun. Mich nerven Deine elitären> Unterstellungen.
Wenn es elitär sein sollte, sein Hirn für mehr zu benutzen als die
Ausrede "ich kann's nicht probieren, weil meine 9 Kollegen das nie
verstehen", dann muß ich mich damit abfinden.
Aber was soll's, ich hatte eigentlich den Plan, mal ein Beispiel zu
bauen, das komplex genug ist, um die Vorteile erkennbar zu machen und
einfach genug, daß es auch mit leichter mental-Gastritis verdaubar ist.
Offenbar kann ich mir die Zeit sparen.
Gerhard O. schrieb:> Naja. Vielleicht wird es besser gehen wie ich mir es ausmale. Allerdings> wird ein Teil der Bemühungen Eine Dokubasis zum Nachschlagen aufzubauen> da ich zur Zeit noch nichts habe.>> Wie ist eigentlich z.B mit der Stringdoku?
Die offizielle Doku zur Sprache und zur libstdc++ findest Du hier:
http://en.cppreference.com/w/> Wenn ich jetzt eine String search machen wollte, geht das mit> trickreicher Operator Magie oder Funktionsaufruf alleine?
Mmh, jetzt bin ich etwas verwirrt: ich war davon ausgegangen, dass Du
ein Grundverständnis von C++ hast?
Der Typ std::string ist kein primitiver DT in C++, sondern in der
libstdc++ definiert (eigentlich als template-Spezialisierung).
Grundsätzlich gilt in der libstdc++ eine Zweiteilung in (generische)
Algorithmen und Datentypen. Das Bindeglied zwischen beidem sind
Iteratoren. Iteratoren kann man im ersten Ansatz als verallgemeinerte
Zeiger ansehen (DT mit den Op * ,-> ,++, !=).
Eine Substring-Suche findest Du als Elementfunktion des DT std::string.
Andere Algorithmen auf den Containern in der Algorithmus-Teilbibliothek.
Ist das jetzt alles neu für Dich?
Würde auch vorschlagen, das Du andere Threads eröffnest, um Deine Fragen
zu stellen.
Wilhelm,
Um diese Zeit hätte ich jetzt keine Antwort mehr erwartet:-) bei mir ist
es fast 23:00 Uhr.
Wilhelm M. schrieb:> Gerhard O. schrieb:>>> Naja. Vielleicht wird es besser gehen wie ich mir es ausmale. Allerdings>> wird ein Teil der Bemühungen Eine Dokubasis zum Nachschlagen aufzubauen>> da ich zur Zeit noch nichts habe.>>>> Wie ist eigentlich z.B mit der Stringdoku?>> Die offizielle Doku zur Sprache und zur libstdc++ findest Du hier:>> http://en.cppreference.com/w/
Danke.
>>> Wenn ich jetzt eine String search machen wollte, geht das mit>> trickreicher Operator Magie oder Funktionsaufruf alleine?>> Mmh, jetzt bin ich etwas verwirrt: ich war davon ausgegangen, dass Du> ein Grundverständnis von C++ hast?
Noch nicht viel weil ich bis jetzt uC nur in C gequält habe. Ich
modifizerte allerdings die Core Serial vom Arduino um RS485 native zu
unterstützen. Das ist auch alles und kam auch ganz gut zurecht damit
weil da ja schon ein funktionierendes Beispiel vorhanden war das ich nur
erweitern mußte.
>> Der Typ std::string ist kein primitiver DT in C++, sondern in der> libstdc++ definiert (eigentlich als template-Spezialisierung).>> Grundsätzlich gilt in der libstdc++ eine Zweiteilung in (generische)> Algorithmen und Datentypen. Das Bindeglied zwischen beidem sind> Iteratoren. Iteratoren kann man im ersten Ansatz als verallgemeinerte> Zeiger ansehen (DT mit den Op * ,-> ,++, !=).>> Eine Substring-Suche findest Du als Elementfunktion des DT std::string.
Ok. Werde ich nachschauen. Ich beginne zu verstehen. Das ist definitiv
sehr "powerful".
> Andere Algorithmen auf den Containern in der Algorithmus-Teilbibliothek.
Vielen Dank. Das werde ich mir gleich vorknöpfen weil es für mich
praktisch wichtig ist.
>> Ist das jetzt alles neu für Dich?
Absolut. Bis jetzt kam ich ja mit C immer zurecht. Will aber meinen
Horizont doch erweitern weil mir einige C++ Sachen beim Arduino als sehr
nützlich vorkamen.
>> Würde auch vorschlagen, das Du andere Threads eröffnest, um Deine Fragen> zu stellen.
Da hast Du recht. Werde ich machen.
Beitrag "Praktische C++ Anwendungsfragen"
Jedenfalls bin ich Dir für alle Deine Ratschläge und Informationen
dankbar.
Gruß,
Gerhard
Roland F. schrieb:> Was meinst du mit "Details"?
u.a.:
- "using namespace std;" in C++
- "int" für Array-Indices
- Makros für alles und jedes statt inline-Funktionen und Konstanten
- Nutzung von "int" statt "int32_t" o.ä.
- *NULL
- char x [7]; x [3] = NULL;
- int x = ... ; char lowerByte = ((char*) &x) [0];
- printf ("%d\n", irgendEinPointer);
... sieht man sehr häufig. Das könnte man gerne besser lehren...
Wegen C++: Das lernt man am Besten mit einem guten Buch. Viele Bücher
sind schlecht. Hier ist eine Liste guter Bücher:
https://stackoverflow.com/a/388282
Dr. Sommer schrieb:> Nutzung von "int" statt "int32_t"
Kann aber gut und gern sinnvoll sein. int32_t schreibt halt zwingend
vor, dass es genau 32 Bits sein müssen – auch dann, wenn das für
irgendeine Architektur vielleicht gerade nicht optimal ist.
int_fast32_t würde sagen: „nimm mindestens 32 Bits, aber es soll schnell
sein“. Das ist das, was man meistens brauchen würde an dieser Stelle.
"int" allein hat aber eine hinreichend garantierte Minimalgröße, dass
es für viele Fälle genügt, und die Annahme ist, dass es für eine
bestimmte Architektur die Größe ist, die auf dieser Maschine am
besten verarbeitbar ist (auf einem AVR sind es daher 16 Bits, auf
einem ARM 32, auf anderen können es auch 64 sein).
Aber ich gebe dir Recht: genau solche Abwägungen müsste man natürlich
besser unter die Leute bringen.
Jörg W. schrieb:> Kann aber gut und gern sinnvoll sein
Klar. Aber die meisten nutzen, wie in Java, für alles int. Man sollte
wissen wann es sinnvoll ist und wann nicht ist. Statt int würde ich aber
auch lieber int_least16_t schreiben, hat die gleiche Bedeutung aber es
zeigt klarer was man haben will.
Possetitjel schrieb:>> Für andere aber nicht. Ich merke deutlich die Unterschiede>> im Denken bei der Zusammenarbeit mit Ingenieuren.>> Nur interessehalber: Welche sind das? Bzw. wie zeigen sie> sich?
Schwierig in Worte zu fassen. Ein Versuch:
- Ingenieure denken in Bauplänen und Komponenten. Alles was nicht als
Blockdiagramm darstellbar ist ist für den Ing kaum fassbar. Software
lässt sich aber nur sehr begrenzt so darstellen, oder immer nur eine
Sichtweise davon...
- Wenn für den Ing zwei Komponenten irgendwie zusammenpassen, ist alles
ok. Aus Software-Sicht ist die Kombination beliebiger Teile oft nicht
sinnvoll, was nicht so leicht vermittelbar ist. Bspw. einen ESP32 an
einem R-PI mit Linux anzuschließen ist nur auf den 3. Blick "irgendwie
komisch".
- Hardware lässt sich gut wasserfall-artig entwickeln, von Anforderungen
bis Tests. Ist bei Software oft weniger angemessen, und agile Prozesse
passen ggf. nicht gut in ein Ingenieurs-Unternehmen. Software ist auch
nie wirklich fertig.
- Für Ing.-Arbeiten lassen sich wunderbar ToDo-Listen und
Arbeitsvorgänge planen - à la der Abteilungsleiter plant wer was wann
macht - das ist bei Software und den komplexen Abhängigkeiten schwierig.
- Ing.-Arbeit ist oft "richtige Arbeit", die man Schritt für Schritt
abarbeiten kann. SW-Entwicklung ist oft ein kreativer Prozess mit
ungewissem Weg, Dauer und Ende.
- Ings haben oft kaum das Deployment/Inbetriebnahme im Blick. Als
Embedded-Entwickler darf man sich dann mit Platinen befassen, die keine
Test-LED's/Taster, Testpunkte, komische JTAG-Stecker, allgemein winzige
unpraktische Stecker haben. Der klitzekleine "SW-Entwicklung"-Schritt
zwischen Löten und Einbauen wird da gern übersehen.
- Ings haben nicht so das Gefühl für Fehlersuche. Wenn da was nicht
klappt stehen die oft ratlos da. Als Informatiker hat man mehr so das
Verlangen möglichst viele Informationen zu sammeln um das Problem
einzugrenzen, so klärt sich schon vieles.
Das soll alles keine Beleidigung sein, sind nur ein paar Erfahrungen.
Ings können haben bestimmt auch genug Probleme mit Informatikern.
Natürlich hängt das alles stark vom Einzelfall ab, und die Probleme
lassen sich mit Kommunikation und Organisation angehen. Aber dran denken
muss man...
Dr. Sommer schrieb:> Funktioniert nicht mit Strings die 0-Bytes enthaltenMarkus F. schrieb:>> ... Strings die 0-Bytes enthalten...>> das ist für C-Programmierer ein Oxymoron.
Ist es nicht. Jeder C-String enthält ein 0-Byte, selbst ein leerer
String.
Aber eben nur eins.
Ein Byte-Array, das mehrere 0-Bytes oder auch keins enthalten kann, ist
eben kein String, sondern ein Mem-Block. Dazu gibt es eigene Funktionen.
Die haben aber den Nachteil, dass sie zwingend als zweiten Parameter
eine Länge brauchen, während zum Lesen eines Strings ein Pointer genügt.
Zum Schreiben von Strings ist ein zweiter Pointer als Begrenzung oder
die Restlänge des Puffers sinnvoll.
Da Strings die Aufgabe haben, sowohl von Menschen als auch von Maschinen
lesbar und schreibbar zu sein, ist die Sonderfunktion des 0-Bytes keine
Beeinträchtigung.
Yalu X. schrieb:> Ich habe mir die Mühe gemacht, deinen ellenlangen Beitrag> von oben durchzulesen,
Ohh. Vielen Dank.
> jetzt musst du dasselbe auch mit meinem tun ;-)
Sehr gern.
> Wenn ich dich richtig verstehe, versucht du, sämtliche> Eigenschaften von Programmiersprachen auf Automaten> abzubilden, um sie dadurch besser zu verstehen.
Ähh... Nein.
Ich habe die Beobachtung gemacht, dass BESTIMMTE Eigen-
schaften von Programmiersprachen für mich sehr viel
leichter verständlich werden, wenn ich sie auf (endliche)
Automaten abbilde.
Das Verständnis fällt mir SO viel leichter, dass ich
mich ernsthaft frage, warum die übliche Darstellung
auf eine so hirnrissig komplizierte Weise erfolgt.
> Kann es sein, dass du dich damit selber blockierst und> so somit genau das Gegenteil von dem erreichst, was du> eigentlich anstrebst?
Sicher kann das sein -- aber erlaube die Gegenfrage:
Was bringt Dich auf den Verdacht, es sei so?
> Was du in deinen Beispielen mittels Automaten beschreibst,> sind im Wesentlichen Ablaufstrukturen (Sprünge, Unter-> programmaufrufe, Objekte mit Memberfunktionen, Parallelität> usw.).
Hmm, ja.
> Im Gegensatz zu Assembler und Ur-Fortran zeichnen sich> moderne Sprachen aber durch weit mehr als nur die von> ihnen unterstützten Ablaufstrukturen aus, als da wären:>> - Datentypen (numerisch, textuell, primitiv, zusammengesetzt,> ...)>> - Typsysteme (stark, schwach, statisch, dynamisch, flach,> hierarchisch, ...)>> - Möglichkeiten der Metaprogrammierung (Lisp-Makros,> C++-Templates, ...)>> - u.v.m.
"If it's not broken, don't fix it."
Warum sollte ich Dinge umdeuten, mit denen ich in der
traditionellen Formulierung keine Verständnisprobleme
habe?
Nehmen wir die Datentypen: Ich habe da nie tiefer drüber
nachgedacht, aber man kennt es ja aus der Physik, dass eine
physikalische Größe aus Zahlenwert und Einheit besteht, und
dass man als Folge dessen nur Größen rechnerisch verknüpfen
darf, deren Einheiten kompatibel sind. (Dafür gibt es sogar
eine m.o.w. algebraische Begründung.)
Das ist ja letztlich genau das, was auch Datentypen im
Computer bewirken; das ist eine vertraute Geschichte.
Warum sollte ich das auf Krampf umdeuten wollen?
[...]
> Ich habe deswegen lange nach einem besseren Ersatz für> diese Maschinchen gesucht und schließlich auch gefunden:>> Mathematische Modelle
Ich verstehe die Worte, nicht aber ihren Sinn: Ein Automat
IST doch (auch bzw. primär) ein mathematisches Modell --
nämlich ein Quintupel (X, Y, Z, f, g) mit bestimmten Eigen-
schaften.
Nur hat dieses mathematische Modell den großen Vorzug, dass
ich sehr einfache elektronische Realisierungen für wenige
Cent bei der eingetragenen Kauffrau in Sande kaufen kann.
Wann hat man dieses Privileg schon mal: Anschauungsmodelle
für mathematische Konzepte, die man im Bastlerladen kaufen
kann?
Und ein weiterer Vorzug: Mir als E-Techniker ist das Modell
des endlichen Automaten vertraut -- also warum sollte ich
dieses Wissen nicht in Anschlag bringen, wenn es möglich
ist?
> Endgültig die Augen aufgegangen sind mir, als ich begann,> mich mit funktionaler Programmierung zu beschäftigen. In> der reinen FP gibt es weder Abläufe noch Zustände, weswegen> die Vorstellung von Maschinchen schon per se zu nichts> führen kann.
Ich bin... verwirrt.
> Mit mathematische Modellen hingegen kann man einige Dinge> tun, die mit den Maschinchen in meinem Kopf kaum möglich> sind:
Wahrscheinlich missverstehe ich Deine Intention gründlich,
aber was ist Automatentheorie für Dich? Sowas wie die
Backförmchen für die Kindergartenkinder? Cargo-Mathematik
(--> Cargo-Kult) für Debile (=Elektrotechniker)?
[...]
> Immer wieder fallen mir bei schwierigen Problemen weitere> Wege ein, die zwar abstrakt anmuten, aber letztendlich> dazu geeignet sind, hinderliche Knoten in Gehirnwindungen> zu lösen und damit die Problemstellung zu vereinfachen.
Naja... ist das nicht die Stärke jeder guten, verständigen
Abstraktion?
"Es gibt nichts praktischeres als eine gute Theorie."
> Und das Beste dabei: Die Erkenntnisse, die man dabei gewinnt,> lassen sich nicht nur auf die FP, sondern mit leichten> Einschränkungen auch auf die klassische Programmierung in> C oder C++ anwenden.
Ich weiss immer noch nicht, worauf Du mit der funktionalen
Programmierung hinauswillst.
Die Sache ist faszinierend, ja -- unter anderem deshalb,
weil sie (genau wie die Deutung durch endliche Automaten)
ohne "Algorithmen" und die dadurch entstehenden "parasitären"
Zustände auskommt.
Vielleicht mache ich einen Fehler, aber ich sehe noch nicht,
wie mir die FP z.B. im Kontext der OOP helfen sollte.
> Was ich damit ausdrücken möchte: Die Informatiker, deren> Geschwurbel du nicht verstehst, sind entweder tatsächlich> Dummschwätzer oder Angeber, oder aber sie denken in Modellen,> die sie persönlich zwar befähigen, selbst schwierigste> Probleme zu lösen, die sich aber leider nicht in deine Welt> der Automaten übersetzen lassen.
Nein, weder -- noch. Völlig anders.
Ich habe kein grundsätzliches Problem mit der theoretischen
Informatik. Das ist halt mathematischer Stoff genau wie
Feldtheorie, Numerik oder Algebra. Es ist hart, sich den
Stoff zu erarbeiten, aber es lohnt sich in der Regel, weil
man sich dauerhaftes Hintergrundwissen aufbaut. Das Hinter-
grundwissen ist zwar interessant, aber kurzfristig nicht
unmittelbar praktisch anwendbar.
Unmittelbar praktisch anwendbar wäre die zuverlässige
Beherrschung einer Programmiersprache. Leider habe ich ein
MASSIVES Problem mit den meisten Büchern, die mir eine
Programmiersprache beibringen wollen. Die Darstellungen
kleben dermaßen schrecklich an syntaktischen Details und
geben so wenig Einblick in die hinterliegenden Konzepte,
dass ich i.d.R. nach wenigen Seiten einen Wutanfall
bekomme.
Wenn ich von Digitaltechnik keine Ahnung hätte, würde ich
mich schätzungsweise deprimiert und demütig in die Ecke
setzen und mich schämen, weil ich so dumm bin.
Sehr zum Nachteil meiner Mitmenschen HABE ich aber gewisse
Grundkenntnisse in Automatentheorie. Gestützt auf diese
Kenntnisse fährt mir ein ums andere Mal in die Nase, dass
die angewandten Informatiker, die die Bücher verfasst
haben, KONSEQUENT alle die schönen, einfachen, klaren
theoretischen Modelle ignorieren, die ihre Fachkollegen
aus der theoretischen Informatik und der Digitaltechnik
bereitgestellt haben.
Man kann (nicht alle, aber) viele Sachverhalte, mit denen
übliche Programmiersprachen hantieren, klar und verständlich
in den Begriffen der Automatentheorie darstellen -- ABER
DAS WIRD NICHT GEMACHT!
Wozu wurden die Begriffe der Automatentheorie entwickelt,
wenn sie dann nicht bei einer der häufigsten Tätigkeiten
in der Informatikausbildung -- nämlich dem Lehren von
Programmiersprachen -- verwendet werden?
Hallo,
Dr. Sommer schrieb:> Wegen C++: Das lernt man am Besten mit einem guten Buch. Viele Bücher> sind schlecht. Hier ist eine Liste guter Bücher:> https://stackoverflow.com/a/388282
Das Problem C++ (oder auch andere Programmiersprachen) zu lernen ist
nicht ein gutes Buch über C++ durch zuarbeiten, sondern die hinter den
neueren Versionen von C++ stehenden Programmierparadigmen zu verstehen.
Jedes mal wenn ich versuche diese Konzepte zu begreifen, muss ich
feststellen, das sich die entsprechende Literatur in syntaktischen
Einzelheiten der Programmiersprache verliert, anstatt erst mal
grundsätzlich zu erklären welche eigentliche Idee hinter bestimmten
Sprachkonstrukten (und den damit verbundenen Datentypen) steht. Mir geht
es da genau wie Possetitjel,
Zitat:
> Leider habe ich einMASSIVES Problem mit den meisten Büchern, die mir> eine Programmiersprache beibringen wollen. Die Darstellungen kleben> dermaßen schrecklich an syntaktischen Details und geben so wenig> Einblick in die hinterliegenden Konzepte, dass ich i.d.R. nach wenigen> Seiten einen Wutanfall bekomme.
rhf
Roland F. schrieb:> Das Problem C++ (oder auch andere Programmiersprachen) zu lernen ist> nicht ein gutes Buch über C++ durch zuarbeiten, sondern die hinter den> neueren Versionen von C++ stehenden Programmierparadigmen zu verstehen.> Jedes mal wenn ich versuche diese Konzepte zu begreifen, muss ich> feststellen, das sich die entsprechende Literatur in syntaktischen> Einzelheiten der Programmiersprache verliert, anstatt erst mal> grundsätzlich zu erklären welche eigentliche Idee hinter bestimmten> Sprachkonstrukten (und den damit verbundenen Datentypen) steht. Mir geht> es da genau wie Possetitjel,
Die Menge der primitiven DT ist ja doch sehr einfach und gering, dann
gibt es noch die abgeleiteten Typen und die modifier
const/volatile/mutable, s.a.:
http://en.cppreference.com/w/cpp/language/type
Nur diese Typen haben einen direkten Bezug zu Sprachkonstrukten.
Oder meinst Du die Templates der libstdc++?
Roland F. schrieb:> Das Problem C++ (oder auch andere Programmiersprachen) zu lernen ist> nicht ein gutes Buch über C++ durch zuarbeiten, sondern die hinter den> neueren Versionen von C++ stehenden Programmierparadigmen zu verstehen.> Jedes mal wenn ich versuche diese Konzepte zu begreifen, muss ich> feststellen, das sich die entsprechende Literatur in syntaktischen> Einzelheiten der Programmiersprache verliert, anstatt erst mal> grundsätzlich zu erklären welche eigentliche Idee hinter bestimmten> Sprachkonstrukten (und den damit verbundenen Datentypen) steht. Mir geht> es da genau wie Possetitjel,
Das kann man meistens nicht den Büchern/Autoren anlasten. Es ist z.B.
schwer die objektorientierten Features von C++ zu verstehen, ohne
grundlegendes OOP Kenntnisse. Es ist allerdings nicht sinnvoll den
kompletten Inhalt eines C++ und eines OOP Lehrbuch in ein einzelnes Buch
zu packen, denn niemand möchte für Grundlangen ein 3000 Seiten 200€ Buch
haben. Und was würde man dann mit den ganzen anderen Themen wie
prozeduale, funktionale und generische Programmierung machen? Alles in
ein Buch packen? Es müssen also immer mehrere Bücher benutzt werden.
mh schrieb:> Roland F. schrieb:>> Das Problem C++ (oder auch andere Programmiersprachen) zu lernen ist>> nicht ein gutes Buch über C++ durch zuarbeiten, sondern die hinter den>> neueren Versionen von C++ stehenden Programmierparadigmen zu verstehen.> Das kann man meistens nicht den Büchern/Autoren anlasten. Es ist z.B.> schwer die objektorientierten Features von C++ zu verstehen, ohne> grundlegendes OOP Kenntnisse.
Das hat sich C++ nun mal leider selber zu eigen gemacht. C#
beispielsweise hat den Vererbungsrattenschwanz auf ein notwendiges Maß
eingeschränkt und es scheint auch zu gehen. Wenn C# kritisiert wird,
dann stets z.B. weil man der automatisierten, hausinternen
Daten-Müllabfuhr genannt GC misstraut bzw. sie für wenig performant
hält, aber nicht, weil man wie bei C++ rückwirkend bis zu August dem
Starken noch Erbansprüche seiner Klasse beifügen kann.
C++ ist für viele anscheinend nur dann erträglich und alltagstauglich,
indem sie es als besseres C verwenden. Das wird auch immer wieder
zugegeben und ist ja auch nicht verwerflich, wirft aber halt Fragen auf
bezüglich des Konzepts und der daraus abgeleiteten Lerntauglichkeit
dieser Sprache. Und die vielen recht oberflächlichen C++ Bücher
untermauern letztlich doch diesen Eindruck. Auch den Autoren dieser
Bücher scheint es offensichtlich große Mühe zu bereiten, die wahren
Vorteile von C++ dem geneigten Leser verständlich zu vermitteln.
Korrektur, muss heißen
" ... aber nicht, weil man NICHT wie bei C++ rückwirkend bis zu August
dem
Starken noch Erbansprüche seiner Klasse beifügen kann."
Possetitjel schrieb:>> Wenn ich dich richtig verstehe, versucht du, sämtliche>> Eigenschaften von Programmiersprachen auf Automaten>> abzubilden, um sie dadurch besser zu verstehen.>> Ähh... Nein.
Ok, dann habe ich dich wahrscheinlich komplett missverstanden.
> Ich habe die Beobachtung gemacht, dass BESTIMMTE Eigen-> schaften von Programmiersprachen für mich sehr viel> leichter verständlich werden, wenn ich sie auf (endliche)> Automaten abbilde.
Mir persönlich geht es eher so:
Diejenigen Aspekte von Programmiersprachen, für die es mir gelingt, sie
auf endliche Automaten abzubilden, verstehe ich auch ohne diese.
Deswegen hat es mich zunächst etwas überrascht, dass das bei dir anders
ist. Aber da hat wohl jeder seine eigene Denkweise, mit der er am besten
klar kommt, was ja vollkommen in Ordnung ist.
> Das Verständnis fällt mir SO viel leichter, dass ich> mich ernsthaft frage, warum die übliche Darstellung> auf eine so hirnrissig komplizierte Weise erfolgt.
Es könnte sein, dass es relativ wenig Leute gibt, die in diesem
Zusammenhang in Automaten denken. Deswegen gibt es ebenso wenige, die
dir etwas in deiner Sprache bzw. Denkweise erklären können.
>> Im Gegensatz zu Assembler und Ur-Fortran zeichnen sich>> moderne Sprachen aber durch weit mehr als nur die von>> ihnen unterstützten Ablaufstrukturen aus, als da wären:>>>> - Datentypen (numerisch, textuell, primitiv, zusammengesetzt,>> ...)>>>> - Typsysteme (stark, schwach, statisch, dynamisch, flach,>> hierarchisch, ...)>>>> - Möglichkeiten der Metaprogrammierung (Lisp-Makros,>> C++-Templates, ...)>>>> - u.v.m.>> "If it's not broken, don't fix it.">> Warum sollte ich Dinge umdeuten, mit denen ich in der> traditionellen Formulierung keine Verständnisprobleme> habe?
Jetzt verstehe ich gar nichts mehr :)
Wenn du nicht nur die Ablaufstrukturen verstanden hast, sondern auch
abstraktere Dinge wie die oben genannten, dann bist du ja fast schon auf
einer Ebene mit Wilhelm, und ich frage mich, was du denn noch nicht
verstanden hast. Vielleicht nennst du mal ein konkretes Beispiel, dann
können wir darüber diskutieren, mit welchen Hilfsmitteln man das am
besten erklären kann.
>> Ich habe deswegen lange nach einem besseren Ersatz für>> diese Maschinchen gesucht und schließlich auch gefunden:>>>> Mathematische Modelle>> Ich verstehe die Worte, nicht aber ihren Sinn: Ein Automat> IST doch (auch bzw. primär) ein mathematisches Modell --> nämlich ein Quintupel (X, Y, Z, f, g) mit bestimmten Eigen-> schaften.
Es ist ein mathematisches Modell, das zur Beschreibung bestimmter
Sachvehalte sehr gut taugt, für andere weniger gut und für wieder andere
überhaupt nicht.
> Nur hat dieses mathematische Modell den großen Vorzug, dass> ich sehr einfache elektronische Realisierungen für wenige> Cent bei der eingetragenen Kauffrau in Sande kaufen kann.
Du baust doch deine Automaten zur Erklärung von Programmieraspekten doch
nicht etwa in realer Elektronik auf? =8o
> Und ein weiterer Vorzug: Mir als E-Techniker ist das Modell> des endlichen Automaten vertraut -- also warum sollte ich> dieses Wissen nicht in Anschlag bringen, wenn es möglich> ist?
Wenn sie dir weiterhelfen, dann ist das in Ordnung. Mir (und
offensichtlich auch Wilhelm) helfen sie nicht weiter. Das ist für mich
ebenfalls in Ordnung, solange ich einen anderen Weg finde, etwas zu
verstehen :)
>> Endgültig die Augen aufgegangen sind mir, als ich begann,>> mich mit funktionaler Programmierung zu beschäftigen. In>> der reinen FP gibt es weder Abläufe noch Zustände, weswegen>> die Vorstellung von Maschinchen schon per se zu nichts>> führen kann.>> Ich bin... verwirrt.
Ich anfangs auch ;-)
> Wahrscheinlich missverstehe ich Deine Intention gründlich,> aber was ist Automatentheorie für Dich? Sowas wie die> Backförmchen für die Kindergartenkinder? Cargo-Mathematik> (--> Cargo-Kult) für Debile (=Elektrotechniker)?
Nein, überhaupt nicht. Ich benutze Automatentheorie durchaus, bspw. als
Hilfsmittel für den Entwurf von Digitalschaltungen. Automaten ohne die
Theorie setze ich manchmal als Entwurfsmuster in der Softwareentwicklung
ein.
> Ich weiss immer noch nicht, worauf Du mit der funktionalen> Programmierung hinauswillst.
Sie hat bei mir dazu geführt, bei der Softwareentwicklung weniger in
Schritt-für-Schritt-Abläufen, sondern mehr in mathematischen Funktionen
zu denken. Das heißt aber nicht, dass ich das "Schrittdenken" komplett
aufgegeben habe, aber ich beschränke es auf diejenigen Anwendungen, die
zu deren Natur es gut passt.
Beispiele:
- Eine Waschmaschinensteuerung schaltet schrittweise, abhängig von der
Zeit und von Sensorinformationen verschiedene Aktoren (Ventile, Pumpen
Trommelantrieb) ein und aus. Dafür ist das Schrittdenken und die
Formalisierung mit Automaten sehr gut geignet.
- Ein Sortieralgorithmus wird zwar vom Prozessor ebenfalls schrittweise
ausgeführt, von der Natur der Sache ist er aber eine mathematische
Funktion, deren Argument eine unsortierte, und deren Funktionswert die
sortierte Liste ist. Einen solchen Algorithmus mittels Automaten zu
beschreiben oder seine Ausführung in einem Debugger Schritt für
Schritt mitzuverfolgen, ist viel Arbeit und bringt für mich keinerlei
Nutzen.
> Die Sache ist faszinierend, ja -- unter anderem deshalb,> weil sie (genau wie die Deutung durch endliche Automaten)> ohne "Algorithmen" und die dadurch entstehenden "parasitären"> Zustände auskommt.> Vielleicht mache ich einen Fehler, aber ich sehe noch nicht,> wie mir die FP z.B. im Kontext der OOP helfen sollte.
So richtig gesehen habe ich das auch erst, als ich es gemacht habe. So
wie einer, der in der OOP zu Hause ist, auch gewöhnliche C-Programme
anders strukturieren wird, als einer, der von klassischem Basic kommt,
wird der C-Code von einem FPler noch einmal anders aussehen. In beiden
Fällen wird der resultierende C-Code an Verständlichkeit, Wartbarkeit
und Eleganz gewinnen.
Dass FP (zwar langsam, aber stetig) zu einem Trend wird, zeigt sich u.a.
darin, dass immer mehr Mainstream-Programmiersprachen (wie bspw. Python,
C# und seit einigen Jahren auch C++), prozedurale, objektorientierte und
funktionale Elemente in sich vereinen. Da sie dem Programmierer kein
bestimmtes Paradigma aufzwingen, ist mit ihnen ein sanfter Einstig in
die jeweiligen Paradigmen möglich.
Yalu X. schrieb:> Dass FP (zwar langsam, aber stetig) zu einem Trend wird, zeigt sich u.a.> darin, dass immer mehr Mainstream-Programmiersprachen (wie bspw. Python,> C# und seit einigen Jahren auch C++), prozedurale, objektorientierte und> funktionale Elemente in sich vereinen.
Und als Zusatz bzw. als das ganz Besondere (meiner Meinung nach) die
generische Programmierung, die sich wunderbar mit FP zusammenfügt. Ich
gebe zu, über die syntaktische Ausgestaltung bei C++ kann man geteilter
Meinung sein ;-) Durch Gewohnheit stört es mich nicht mehr.
> Da sie dem Programmierer kein> bestimmtes Paradigma aufzwingen, ist mit ihnen ein sanfter Einstig in> die jeweiligen Paradigmen möglich.
Und das sehe ich als die ganz große Stärke gerade von C++ an. Dadurch
kann man m.E. eine sehr große Expressivität im Code erreichen.
Dr. Sommer schrieb:> Klar. Aber die meisten nutzen, wie in Java, für alles int. Man sollte> wissen wann es sinnvoll ist und wann nicht ist.
Toll finde ich die Programmierer, die für eine Masse oder für ein
Volumen int verwenden (in C oder C++).
:-(
Mark B. schrieb:> Dr. Sommer schrieb:>> Klar. Aber die meisten nutzen, wie in Java, für alles int. Man sollte>> wissen wann es sinnvoll ist und wann nicht ist.>> Toll finde ich die Programmierer, die für eine Masse oder für ein> Volumen int verwenden (in C oder C++).
Ach, die Diskussion führe ich hier doch regelmäßig! Alles ist ein int,
und wenn nicht, dann ein String.
Markus F. schrieb:> Dr. Sommer schrieb:>> ... Strings die 0-Bytes enthalten...>> das ist für C-Programmierer ein Oxymoron.
Im Gegentum: Ein C-String, der am Ende kein NUL enthält, ist kaputt.
Also ist's eher eine Tautologie.
Alexander T. schrieb:> Im Gegentum: Ein C-String, der am Ende kein NUL enthält, ist kaputt.> Also ist's eher eine Tautologie
Und was ist NUL? Hoffentlich nicht NULL?
Ersetzt einfach "String" durch Byte-Array, dann passt es wieder. Oft
genug hat man Byte-Arrays die 0-Bytes enthalten können.
Lustig wird sowas:
1
std::stringfileName=getUserInput();
2
if(fileName=="geheim.txt")
3
Error("Permission denied");
4
fopen(fileName.c_str(),"r");
Wenn der User jetzt "geheim.txt\0bla" eingibt, greift die Sicherheits
Prüfung nicht, aber fopen sieht nur "geheim.txt"... Wer ist hier schuld?
Sowas ähnliches ist/war eine Sucherheitslücke in PHP.
Wilhelm M. schrieb:> Yalu X. schrieb:>>> Dass FP (zwar langsam, aber stetig) zu einem Trend wird, zeigt sich u.a.>> darin, dass immer mehr Mainstream-Programmiersprachen (wie bspw. Python,>> C# und seit einigen Jahren auch C++), prozedurale, objektorientierte und>> funktionale Elemente in sich vereinen.>> Und als Zusatz bzw. als das ganz Besondere (meiner Meinung nach) die> generische Programmierung, die sich wunderbar mit FP zusammenfügt. Ich> gebe zu, über die syntaktische Ausgestaltung bei C++ kann man geteilter> Meinung sein ;-)
Am besten ist es, wenn man die Generizität für jede Funktion sozusagen
gratis mit dazu bekommt, ohne dass man dazu eine spezielle Syntax
bemühen muss. Haskell und F# zeigen, wie's geht.
Eine Funktion, die die Summe einer Zahlenfolge berechnet, könnte in
Haskell bspw. so definiert werden:
1
mySum = foldl' (+) 0
foldl' ist dabei eine Bibliotheksfunktion, (+) die Funktion, die auf die
Elemente der Folge angewandt werden soll, und 0 der Initialwert für
die Aufsummierung.
Der Aufruf
1
mySum [1, 2, 5]
liefert das Resultat 8. Die Funktion erlaubt dabei beliebige faltbare
Argumente (List, Array, Set usw.) mit beliebigen numerischen Elementen
(Integer, Rational, Double, Complex Double usw.).
So leicht kann das Schreiben von wiederverwendbarem Code gehen :)
Dr. Sommer schrieb:> Lustig wird sowas:std::string fileName = getUserInput();> if(fileName == "geheim.txt")> Error ("Permission denied");> fopen (fileName.c_str (), "r");Wenn der User jetzt "geheim.txt\0bla"> eingibt, greift die Sicherheits> Prüfung nicht, aber fopen sieht nur "geheim.txt"... Wer ist hier schuld?> Sowas ähnliches ist/war eine Sucherheitslücke in PHP.
Mit purem C wäre das nicht passiert.
Der Murks liegt also bei getUserInput() und der Sicherheitsprüfung, für
die die Konstrukteure von std::string verantwortlich sind.
> Wenn der User jetzt "geheim.txt\0bla" eingibt, greift die Sicherheits> Prüfung nicht, aber fopen sieht nur "geheim.txt"... Wer ist hier schuld?> Sowas ähnliches ist/war eine Sucherheitslücke in PHP.
Man mischt ja auch nicht C Code mit C++ Code. Das sollte man nur machen,
wenn es gar nicht anders geht.
Dr. Sommer schrieb:> Statt int würde ich aber auch lieber int_least16_t schreiben, hat die> gleiche Bedeutung aber es zeigt klarer was man haben will.
int_fast16_t :)
int_least16_t würde ggf. auf Kosten von Rechenzeit (Bitmaskierung)
verlangen, dass es möglichst 16 Bit sind, dürfen nur dann mehr sein,
wenn die Architektur gar nicht mit 16-Bit-Einheiten umgehen kann.
Zur ursprünglichen Frage:
Mark W. schrieb:> schreibt Ihr auch gelegentlich mal Code, nur um Zeilen zu sparen?
Nein, nie.
Mark W. schrieb:> Oder geht das gar nicht?
Ja!
Erst die Aufgabe analysieren und dafür großzügig Zeit nehmen, dann das
Programm (gilt auch für Hardware) entwickeln und siehe da, man spart
insgesamt gesehen Zeit!
Keiner N. schrieb:> Man mischt ja auch nicht C Code mit C++ Code. Das sollte man nur machen,> wenn es gar nicht anders geht.
Leider sind die meisten Kernel in C geschrieben, und syscalls wie open
nutzen 0-terminierte Strings, auch wenn man sie direkt aus C++ aus
aufruft.
Jobst Q. schrieb:> Mit purem C wäre das nicht passiert.
Mit purem C++ auch nicht. Leider ist POSIX C-orientiert...
Jobst Q. schrieb:> für die die Konstrukteure von std::string verantwortlich sind.
Die Entwickler von std::string können wohl kaum was für diese Prüfung.
Man sollte wohl vor der Prüfung eventuelle 0-Bytes suchen... Aber wer
denkt schon an sowas.
Keiner N. schrieb:> Man mischt ja auch nicht C Code mit C++ Code. Das sollte man nur machen,> wenn es gar nicht anders geht.
C++ ist eine Erweiterung von C. Das ist ja auch der Vorteil gegenüber
anderen objektorientierten Sprachen. Also sollte es kompatibel mit C
sein.
Eine Neudefinition von String von einer Zeichenfolge, die mit dem
Null-Byte abgeschlossen wird, zu einem beliebigen Byte-Array ist ein
schwerwiegender Konstruktionsfehler.
Dr. Sommer schrieb:> Die Entwickler von std::string können wohl kaum was für diese Prüfung.> Man sollte wohl vor der Prüfung eventuelle 0-Bytes suchen... Aber wer> denkt schon an sowas.
Ich wollte gerade schreiben, dass die Prüfung auf '\0'-Zeichen innerhalb
des Dateinamens Aufgabe von [i][o]fstream::open(string &, ...) wäre,
denn genau hier geschieht die Umwandlung eines std::string-Dateinamens
in einen POSIX-, d.h. C-Dateinamen, und der Nutzer solcher High-Level-
Bibliotheksfunktionen sollte sich nicht darum kümmern müssen, ob sein
Betriebssystem POSIX-konform ist oder nicht.
Allerdings hat mich das ISO-Dokument eines Besseren belehrt:
Daraus geht hervor, dass der Dateiname am ersten '\0'-Zeichen unabhängig
vom Betriebssystem immer abgeschnitten wird und sogar werden muss. Wer
darauf reinfällt, hat halt vorher nicht genau genug nachgelesen ;-)
Vor C++11 gab es die open()-Variante mit dem std::string-Dateinamen noch
nicht, weswegen der Programmierer die c_str()-Konvertierung selber
hinschreiben musste, und somit eher auf das Problem aufmerksam wurde.
Die mit C++11 eingeführte Falle hätte man anständigerweise entschärfen
können, indem man in open() eine Prüfung auf '\0'-Zeichen eingebaut
hätte. Man hat es nicht getan, was wieder einmal bestätigt, dass die
Programmiererei kein Ponyhof ist, sondern nur der des Lesens Mächtige
erfolgreich sein kann ;-)
Yalu X. schrieb:> Eine Funktion, die die Summe einer Zahlenfolge berechnet, könnte in> Haskell bspw. so definiert werden:>>>
1
> mySum = foldl' (+) 0
2
>
>> foldl' ist dabei eine Bibliotheksfunktion, (+) die Funktion, die auf die> Elemente der Folge angewandt werden soll, und 0 der Initialwert für> die Aufsummierung.>> Der Aufruf>>>
1
> mySum [1, 2, 5]
2
>
>> liefert das Resultat 8. Die Funktion erlaubt dabei beliebige faltbare> Argumente (List, Array, Set usw.) mit beliebigen numerischen Elementen> (Integer, Rational, Double, Complex Double usw.).>> So leicht kann das Schreiben von wiederverwendbarem Code gehen :)
In C++:
Hallo,
mh schrieb:> Es ist allerdings nicht sinnvoll den kompletten Inhalt eines C++ und> eines OOP Lehrbuch in ein einzelnes Buch zu packen, denn niemand möchte> für Grundlangen ein 3000 Seiten 200€ Buch haben.
Ja, das ist richtig. Aber das Buch "Einführung in die Programmierung mit
C++" von Bjarne Stroustrup hat z.B. 1224 Seiten und trotzdem gibt es
keinen Platz für einen Überblick über die Konzepte, die hinter C++
stehen.
Dafür findet man im Kapitel 1 unter 1.5 "Computer sind allgegenwärtig"
eine _9_-seitige Aufstellung über Lebensbereiche, in denen Computer eine
wichtige Rolle spielen (das angeeignete Wissen wird dann mit Frage wie
"Wo spielt Software eine wichtige Rolle?. Nennen Sie einige Beispiele"
abgefragt. Mal ehrlich: was soll das?). Wenn für "sowas" Platz ist, dann
sollte es doch ein leichtes sein, auf 20-30 Seiten die Ideen, die hinter
C++ stehen zu beschreiben.
> Und was würde man dann mit den ganzen anderen Themen wie> prozeduale, funktionale und generische Programmierung machen? Alles in> ein Buch packen?
Da stellt sich die Frage was die Aufgabe eines
Programmiersprachenlehrbuches ist. Wenn die Darstellung der Konzepte
nicht dazu gehört, reicht ja eigentlich auch die Sprachreferenz der
aktuellen Version.
> Es müssen also immer mehrere Bücher benutzt werden.
Darauf wird es wohl hinauslaufen. Das erinnert mich allerdings an eine
Aussage eines Lehrers bezüglich des Lernens von Fremdsprachen. Er war
der Meinung, das man (europäische) Sprachen viel einfacher erlernen
könnte wenn man vorher Latein gelernt hätte. Da ist sicherlich auch was
dran, aber wenn jemand nur Französisch lernen will, kann man ja nicht
sagen "dann mach erst mal das große Latinum, danach ist Französisch ganz
einfach".
Vielleicht hast du aber recht und es geht wirklich nicht anders.
Allerdings stellt sich dann die Frage ob die momentan aktuellen
Programmiersprachenkonzepte wirklich sinnvoll sind. In Anbetracht der
der immer größer werdenden Wichtigkeit Software erstellen zu können,
kann man nicht erwarten das jeder zukünftige Programmierer über intimste
Informatikkenntnisse verfügt.
rhf
Roland F. schrieb:> Ja, das ist richtig. Aber das Buch "Einführung in die Programmierung mit> C++" von Bjarne Stroustrup hat z.B. 1224 Seiten und trotzdem gibt es> keinen Platz für einen Überblick über die Konzepte, die hinter C++> stehen.> Dafür findet man im Kapitel 1 unter 1.5 "Computer sind allgegenwärtig"> eine _9_-seitige Aufstellung über Lebensbereiche, in denen Computer eine> wichtige Rolle spielen (das angeeignete Wissen wird dann mit Frage wie> "Wo spielt Software eine wichtige Rolle?. Nennen Sie einige Beispiele"> abgefragt. Mal ehrlich: was soll das?).
Das ist natürlich unverständlich. Allerdings ist das Buch wohl auch
einfach hauptsächlich für Studenten und Dozenten geschrieben. Sieht für
mich jedenfalls so aus.
Roland F. schrieb:> Wenn für "sowas" Platz ist, dann> sollte es doch ein leichtes sein, auf 20-30 Seiten die Ideen, die hinter> C++ stehen zu beschreiben.
Das wird nicht funktionieren, einfach weil C++ eine Multiparadigma
Sprache ist. Da braucht es dann schon ein paar Seiten mehr, um alle zu
behandeln.
Roland F. schrieb:> Vielleicht hast du aber recht und es geht wirklich nicht anders.> Allerdings stellt sich dann die Frage ob die momentan aktuellen> Programmiersprachenkonzepte wirklich sinnvoll sind. In Anbetracht der> der immer größer werdenden Wichtigkeit Software erstellen zu können,> kann man nicht erwarten das jeder zukünftige Programmierer über intimste> Informatikkenntnisse verfügt.
Die Konzepte sind völlig in Ordnung. Aber wenn man zu viel auf einmal
lernen will, wird man wahrscheinlich daran scheitern. Man muss sich halt
fragen, ob es sinnvoll ist gleichzeitig das Programmieren zu lernen,
eine solche mächtige Programmiersprache wie C++ und dann noch ein
Paradigma wie OOP. Das ist einfach zu viel.
Deshalb würde ich nie und nimmer C++ bei Anfängern für die Lehre
einsetzen. Das ist eine Sprache, genauso wie C, die ganz klar die
erfahrenen Nutzer ansprechen will und auf Anfänger keine Rücksicht
nimmt.
Bei uns im Studium gab es uns die Informatiker und dann die
Wirtschaftsinformatiker. Wir haben mit C und C++ angefangen, die haben
ausschließlich Java gemacht. Und wer konnte insgesamt besser mit dem
Programmieren zurecht (mal diejenigen ausgenommen, die sowie schon
Programmieren konnten)? Tatsächlich die Wirtschaftsinformatiker, weil
ihnen die Sprache weniger Steine in den Weg gelegt hatte. Bei uns hatten
die Studenten schon mit C zu kämpfen (Zeiger, Speicherverwaltung,
nullterminierte Strings etc.), bei C++ war dann erst recht die Hölle
los. Auch ist mir aufgefallen, dass die Wirt.Inf. OOP sehr schnell intus
hatten. Erstens kannten die gar nichts anderes und zweitens ist das
ganze Thema in Java viel verständlicher (oder die Autoren davon können
es besser erklären).
Also mein Ratschlag: wer OOP lernen will, sollte einen weiten Bogen um
C++ machen und lieber C# oder Java dafür hernehmen. Es ist wirklich viel
einfacher. Danach kann man sich mit C++ befassen. Ich habe das selber so
gemacht und bin damit sehr gut gefahren, heute ist C++ meine
Lieblingssprache.
Dr. Sommer schrieb:> Die Entwickler von std::string können wohl kaum was für diese Prüfung.> Man sollte wohl vor der Prüfung eventuelle 0-Bytes suchen... Aber wer> denkt schon an sowas.
Der Murks fängt doch schon damit an, dass es überhaupt möglich ist ein
Null-Byte inmitten eines Strings einzugeben. Die Funktion getUserInput()
in deinem Beispiel kenne ich nicht und weiß daher auch nicht,ob die
Entwickler von std::string dafür verantwortlich sind.
Aber spätestens beim Vergleich mit dem überladenen Operator == hätten
sie dafür sorgen können, dass ihre Strings mit den üblichen C-Strings
kompatibel sind.
Bei der Entwicklung einer neuen Sprache wäre es egal, ob sie einen
String als beliebiges Bytearray definieren. Aber als Erweiterung von C
ist diese Inkompatibilität nicht zu verantworten.
Jobst Q. schrieb:> Die Funktion getUserInput()> in deinem Beispiel kenne ich nicht und weiß daher auch nicht,ob die> Entwickler von std::string dafür verantwortlich sind.
Die hab ich mir ausgedacht als Platzhalter für irgendeine Art von
Eingabe. Könnte z.B. über ein Netzwerk kommen.
BMP-Dateien enthalten z.B. Nullbytes. Wenn man die in einen std::string
einliest möchte man die erhalten. Wenn man also eine Eingabe/Protokoll
hat welches allgemein Binär-Daten überträgt, und es auch für Texte
nutzt, werden 0-Bytes mit übernommen. Dies ist z.B. bei HTTP-Formularen
der Fall; hier könnte ein Angreifer 0-Bytes mit senden. 0-Bytes in HTTP
komplett auszuschließen würde aber das Hochladen von BMP-Dateien
verhindern.
Die 0-Bytes sind auch kein Problem, bis man ein solches Byte-Array an
eine C/POSIX-Funktion übergibt.
Jobst Q. schrieb:> Aber spätestens beim Vergleich mit dem überladenen Operator == hätten> sie dafür sorgen können, dass ihre Strings mit den üblichen C-Strings> kompatibel sind.
Du meinst, es soll immer nur bis zum 0-Byte verglichen werden? Dann wäre
also std::string("foo\0bar") == "foo" wahr, aber std::string("foo\0bar")
== std::string("foo") falsch? Auch nicht sehr schön.
Jobst Q. schrieb:> Aber als Erweiterung von C> ist diese Inkompatibilität nicht zu verantworten.
std::string ist keine Erweiterung von "const char*" und somit von
C-Strings!!! std::string ist ein Datentyp für Zeichen-Arrays inklusive
0-Bytes, wobei ein Zeichen char, wchar, char32_t usw sein kann. Wenn man
unvorsichtigerweise c_str () aufruft und die Länge nicht mit
verarbeitet, nutzt man es halt falsch.
C-Strings funktionieren in C++ noch genauso, aber std::string ist eben
kein Wrapper für C-Strings.
Dr. Sommer schrieb:> Jobst Q. schrieb:>> Aber spätestens beim Vergleich mit dem überladenen Operator == hätten>> sie dafür sorgen können, dass ihre Strings mit den üblichen C-Strings>> kompatibel sind.> Du meinst, es soll immer nur bis zum 0-Byte verglichen werden? Dann wäre> also std::string("foo\0bar") == "foo" wahr, aber std::string("foo\0bar")> == std::string("foo") falsch? Auch nicht sehr schön.
Der Ctor von std::string interpretiert den C-String auch richtig. Also
std::string("foo\0bar") hat die Länge 3, denn "foo\0bar" ist ein
C-String der Länge 3 (per Konvention).
Einen String aus einem std::byte Array zu konstruieren geht nicht.
Der Fehler liegt ggf. schon in dem Netzwerkbeispiel darin, die Bytes vom
Netzwerk als char zu deklarieren, was sie ja nicht sind. Es sind Bytes.
Wilhelm M. schrieb:> Der Ctor von std::string interpretiert den C-String auch richtig. Also> std::string("foo\0bar") hat die Länge 3, denn "foo\0bar" ist ein> C-String der Länge 3 (per Konvention).
Achja, ich hatte irgendwie in Erinnerung dass die dem template-Trick
nutzen um die tatsächliche Länge zu erhalten... Ok, wenn man 0-Bytes
übergibt muss man die Länge angeben:
1
std::string("foo\0bar",7);
Wilhelm M. schrieb:> die BYtes vom> Netzwerk als char zu deklarieren, was sie ja nicht sind. Es sind Bytes.
Okay, wie hat man dann Bytes vom Netzwerk interpretiert bevor es
std::byte gab? byte ist ja auch nur als enum vom typ unsigned char
definiert. char darf definitiv 0 werden.
In Anbetracht der Tatsache dass die read/write -Funktionen von
istream/ostream "char*" akzeptieren hätte ich jetzt gedacht, dass man
char-Arrays, und damit auch std::string, sehr wohl zum Speichern von
Netzwerkdaten nutzen kann.
PS: Das User-Defined Literal "s" für std::string übernimmt 0-Bytes
korrekt:
1
#include<cstdio>
2
#include<string>
3
#include<iostream>
4
5
intmain()
6
{
7
usingnamespacestd::string_literals;
8
9
std::strings1="abc\0\0def";
10
std::strings2="abc\0\0def"s;
11
std::cout<<"s1: "<<s1.size()<<" \""<<s1<<"\"\n";
12
std::cout<<"s2: "<<s2.size()<<" \""<<s2<<"\"\n";
13
std::puts(s2.c_str());
14
std::fwrite(s2.data(),1,s2.size(),stdout);
15
std::puts("");
16
}
Ausgabe:
1
s1: 3 "abc"
2
s2: 8 "abc^@def"
3
abc
4
abc^@def
http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s
Der << Operator gibt den ganzen String aus, auch nach dem 0-Byte, weil
das eine "richtige" C++-Ausgabe ist welche eben die Länge auswertet.
puts geht nur bis zum 0-Byte, aber wenn man an fwrite die Länge übergibt
wird alles ausgegeben. Die 0-Bytes werden entsprechend dem Terminal gar
nicht oder irgendwie umschrieben ausgegeben (hier: ^@).
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Der Ctor von std::string interpretiert den C-String auch richtig. Also>> std::string("foo\0bar") hat die Länge 3, denn "foo\0bar" ist ein>> C-String der Länge 3 (per Konvention).>> Achja, ich hatte irgendwie in Erinnerung dass die dem template-Trick> nutzen um die tatsächliche Länge zu erhalten... Ok, wenn man 0-Bytes> übergibt muss man die Länge angeben:>
1
std::string("foo\0bar",7);
Ja, denn der C-String endet per Definitionem am Sentinel. Deswegen macht
der Typw.-ctor von std::string das auch korrekt.
> Wilhelm M. schrieb:>> die BYtes vom>> Netzwerk als char zu deklarieren, was sie ja nicht sind. Es sind Bytes.> Okay, wie hat man dann Bytes vom Netzwerk interpretiert bevor es> std::byte gab?
Konnte man ja machen seit es scoped enums gibt (C++11).
> byte ist ja auch nur als enum vom typ unsigned char> definiert.
Aber eben nich implizit konvertierbar in einen arithmetischen Typ
(char).
> char darf definitiv 0 werden.
Ja klar.
> In Anbetracht der Tatsache dass die read/write -Funktionen von> istream/ostream "char*" akzeptieren hätte ich jetzt gedacht, dass man> char-Arrays, und damit auch std::string, sehr wohl zum Speichern von> Netzwerkdaten nutzen kann.
Das ist doch nur ein C-Krücke, für ein Byte ein char zu nehmen. In C
muss man das so machen schlechterdings.
Dr. Sommer schrieb:> PS: Das User-Defined Literal "s" für std::string übernimmt 0-Bytes> korrekt:
Beide sind korrekt (s.o.): d.h. sie interpretieren den Quelldatentyp
richtig.
Wilhelm M. schrieb:> Das ist doch nur ein C-Krücke, für ein Byte ein char zu nehmen. In C> muss man das so machen schlechterdings.
Und wie macht man es in C++03? In C++17 arbeiten die read/write
Funktionen immer noch mit "char*".
Und was willst du eigentlich sagen? Dass man in dem Code-Snippet kein
std::string hätte verwenden dürfen, sondern std::byte? Wie wäre das in
C++03 gegangen? Dass man mit strcmp hätte vergleichen müssen?
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Das ist doch nur ein C-Krücke, für ein Byte ein char zu nehmen. In C>> muss man das so machen schlechterdings.>> Und wie macht man es in C++03?
Das war vor 15 Jahren, das interessiert mich wirklich nicht mehr.
struct byte {...};
> In C++17 arbeiten die read/write> Funktionen immer noch mit "char*".
Nein, mit void*.
std::fwrite ist ein namespace-aware wrapper für POSIX-fwrite, mehr
nicht.
> Und was willst du eigentlich sagen? Dass man in dem Code-Snippet kein> std::string hätte verwenden dürfen, sondern std::byte?
Wenn man einen Protokollbuffer mit binären, nicht-numerischen Daten hat,
dann wäre das ein std::array<std::byte, ...>, oder ein
std::vector<std::byte>, aber kein std::string.
> Wie wäre das in> C++03 gegangen?
Ja, aber da mache ich mir 15-Jahre später keine Gedanken mehr drüber.
> Dass man mit strcmp hätte vergleichen müssen?
Das vergleicht wieder nur C-Strings ... mit der (impliziten) Annahme,
dass die übergebenen Zeiger auf eine Folge (mindestens eins) Zeichen des
Typs const char zeigen, und dass diese Folge hoffentlich (keiner weiß
es) mit '\0' abgeschlossen ist. Falls nicht ... ok wir kennen die Story.
Sowas ist einfach nur Murks.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Der Ctor von std::string interpretiert den C-String auch richtig. Also>> std::string("foo\0bar") hat die Länge 3, denn "foo\0bar" ist ein>> C-String der Länge 3 (per Konvention).>> Achja, ich hatte irgendwie in Erinnerung dass die dem template-Trick> nutzen um die tatsächliche Länge zu erhalten...
Ja, sowas hatte ich hier mal gepostet, damit man C-Strings (bspw. für
AVR) automatisch in bestimmte Sections (flash) legen kann. Dazu hatte
ich dann ein UDL-Op definiert: "abc"_pgm ist dann im Flash. Man kann
auch das getrost N-mal im Code verwenden, es wird nur einmal ins flash
gepackt.
Wilhelm M. schrieb:> Das war vor 15 Jahren, das interessiert mich wirklich nicht mehr.
Also keine Erklärung. Top.
Wilhelm M. schrieb:> Nein, mit void*.http://en.cppreference.com/w/cpp/io/basic_istream/read
Also hier steht char_type und das ist char bei std::ifstream.
Wilhelm M. schrieb:> aber kein std::string.
Wer sagt das? Und warum kann std::string dann problemlos damit umgehen?
Das o.g. Problem existiert nur bei der Nutzung als C-String.
Wilhelm M. schrieb:> Ja, sowas hatte ich hier mal gepostet
Daher kenn ich das nicht...
Dr. Sommer schrieb:> BMP-Dateien enthalten z.B. Nullbytes. Wenn man die in einen std::string> einliest möchte man die erhalten.
Was soll das für einen Sinn haben, eine Binärdatei in einen String
einzulesen?
> Wenn man also eine Eingabe/Protokoll> hat welches allgemein Binär-Daten überträgt, und es auch für Texte> nutzt, werden 0-Bytes mit übernommen. Dies ist z.B. bei HTTP-Formularen> der Fall; hier könnte ein Angreifer 0-Bytes mit senden. 0-Bytes in HTTP> komplett auszuschließen würde aber das Hochladen von BMP-Dateien> verhindern.
HTTP heißt Hypertext Transfer Protokoll. Es geht also um Texte. 0-Bytes
haben in Texten aber nichts zu suchen.
Um Binärdateien zu übertragen, werden sie meines Wissens mit Base64 oder
ähnlichem in Textdateien umgewandelt.
> Die 0-Bytes sind auch kein Problem, bis man ein solches Byte-Array an> eine C/POSIX-Funktion übergibt.
Sie sind auch in purem C kein Problem, wenn man die mem-Funktionen
verwendet. Der Fehler ist, die Byte-Arrays String zu nennen.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Das war vor 15 Jahren, das interessiert mich wirklich nicht mehr.>> Also keine Erklärung. Top.
Lies genau: steht oben.
>> Wilhelm M. schrieb:>> Nein, mit void*.>> http://en.cppreference.com/w/cpp/io/basic_istream/read> Also hier steht char_type und das ist char bei std::ifstream.
Du hast oben aber std::fwrite() benutzt.
>> Wilhelm M. schrieb:>> aber kein std::string.>> Wer sagt das? Und warum kann std::string dann problemlos damit umgehen?
Wenn Du die Protokollintegrität sicherstellen kannst und Du wirklich nur
Zeichen überträgt, kannst Du es. Aber das wolltest Du ja nicht. Dein
Beispiel zielt auf andere Szenarien ab. Und hier ist das Empfangene erst
mal nur eine Folge von Bytes. Um es als eine Menge von Strings zu
interpretieren, brauchst Du dann eben einen (robusten) Parser. Der
filtert dann solche Sachen aus.
Dr. Sommer schrieb:> Leider sind die meisten Kernel in C geschrieben, und syscalls wie open> nutzen 0-terminierte Strings, auch wenn man sie direkt aus C++ aus> aufruft.
Ehrlich mal, POSIX hat genau zwei „verbotene“ Zeichen in Dateinamen,
das ist das Nullbyte und der Schrägstrich.
Vergleich' das mal mit anderen Betriebssystemen …
Ich hatte das mal für das EA eDIPTFT43-A benötigt, daß Arrays \0
beinhalten. Man kann sie als Strings definieren, aber natürlich nicht
mit Stringfunktionen ausgeben.
Ich hab das mit einen Macro gelöst, was per sizeof die Länge ermittelt.
Da an Strings immer ein 0-Byte angehängt wird, mußte ich noch 1
abziehen:
1
#define TFT_FKT(x) tft_wr( sizeof(x) - 1, x, 1 )
2
uint8_ttft_wr(uint8_tlen,uint8_t*dat,boolflash);// write to GLCD from SRAM or Flash
Wilhelm M. schrieb:> Mmh ...> void init(uint8_t* s) {> TFT_FKT(s);> }>> int main() {> init(INIT);> }
So geht's nicht, aber so, wie Peter geschrieben hat, schon.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Mmh ...>> void init(uint8_t* s) {>> TFT_FKT(s);>> }>>>> int main() {>> init(INIT);>> }>> So geht's nicht, aber so, wie Peter geschrieben hat, schon.
Das ist mir schon klar: es ist DER Standardfehler. Deswegen sollte man
den sizeof()-Operator nicht dort benutzen, wo ein Array-Bezeichner zu
einem Zeiger zerfällt.
Wilhelm M. schrieb:> Deswegen sollte man den sizeof()-Operator nicht dort benutzen, wo ein> Array-Bezeichner zu einem Zeiger zerfällt.
Ich glaube, dessen ist sich Peter durchaus bewusst.
Deswegen übergibt er INIT ja auch nicht per Funktionsargument an
tft_init, sondern greift direkt darauf zu.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Deswegen sollte man den sizeof()-Operator nicht dort benutzen, wo ein>> Array-Bezeichner zu einem Zeiger zerfällt.>> Ich glaube, dessen ist sich Peter durchaus bewusst.
Ihm mag das ja klar sein. Trotzdem fällt damit dieses Macro in die
Kategorie "Leicht falsch zu benutzen".
> Deswegen übergibt er INIT ja auch nicht per Funktionsargument an> tft_init, sondern greift direkt darauf zu.
Du siehst aber, wie schnell man den Fehler machen kann. Vor allem etwas
"unbedarfte" Anwender, die sich über dieses function-like Macro keine
gedanken machen. So etwas sollte heute nicht mehr möglich sein!
Wilhelm M. schrieb:> Trotzdem fällt damit dieses Macro in die Kategorie "Leicht falsch zu> benutzen".
Genau darum schreibt man ja Makros auch GROSS. Damit ist klar, dass
es ein Makro ist und eben keine Funktion, und dass man sich um dessen
Randbedingungen Gedanken machen muss, wenn man ihn benutzt.
Klar könnte man das in C++ alles viel schöner und eleganter schreiben.
Das hilft dir aber gar nichts, wenn du sowas in einem Projekt brauchst,
das über x Jahre mehrere hunderttausend Codezeilen akkumuliert hat, und
für das dir kein Kunde den Aufwand bezahlen würde, es ohne grundlegende
Erweiterung der Funktionalität nur der Eleganz und Schönheit wegen von
C in eine andere Sprache umzuschreiben.
Wilhelm M. schrieb:> Trotzdem fällt damit dieses Macro in die Kategorie "Leicht falsch zu> benutzen".
Fällt nicht das komplette C/C++ in diese Kategorie? ;-)
SCNR
Jörg W. schrieb:> Wilhelm M. schrieb:>> Trotzdem fällt damit dieses Macro in die Kategorie "Leicht falsch zu>> benutzen".>> Genau darum schreibt man ja Makros auch GROSS.
Was aber für den Präprozessor / Compiler unerheblich ist.
> Damit ist klar, dass> es ein Makro ist und eben keine Funktion, und dass man sich um dessen> Randbedingungen Gedanken machen muss, wenn man ihn benutzt.
Wenn sich alle Programmierer immer alle Gedanken machen würde, gäbe es
keine Bugs. Dem scheint aber nicht so zu sein ;-) Es ist besser, wenn
der Code bei falscher Verwendung der Schnittstelle nicht compiliert.
> Klar könnte man das in C++ alles viel schöner und eleganter schreiben.
Du kannst meine Gedanken lesen ;-)
Es wäre schöner, eleganter, sicherer und vermutlich effizienter gewesen.
> Das hilft dir aber gar nichts, wenn du sowas in einem Projekt brauchst,> das über x Jahre mehrere hunderttausend Codezeilen akkumuliert hat, und> für das dir kein Kunde den Aufwand bezahlen würde, es ohne grundlegende> Erweiterung der Funktionalität nur der Eleganz und Schönheit wegen von> C in eine andere Sprache umzuschreiben.
Das wollte ich damit auch gar nicht bezwecken. Ich kenne so etwas zur
Genüge.
Aber: wenn man so etwas (m.E. Murks) immer wieder hier postet, wird sich
an der Situation leider nichts ändern. Man muss zumindest deutlich
hervorgehoben werden. Was ich damit getan habe.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Trotzdem fällt damit dieses Macro in die Kategorie "Leicht falsch zu>> benutzen".>> Fällt nicht das komplette C/C++ in diese Kategorie? ;-)
Das will ich gar nicht in Gänze bestreiten.
Allerdings sehe ich einen wesentlichen Unterschied:
In C kann man es leider nicht wirklich besser machen, in C++ hat man die
Möglichkeiten. Und gute Library-API-Designer nutzen diese Möglichkeiten.
Jörg W. schrieb:> Klar könnte man das in C++ alles viel schöner und eleganter schreiben.Das Beispiel braucht kein C++ um einigermassen wasserdicht zu werden.
Statt das sizeof() ins Makro zu schreiben eine entsprechende Konstante
definiert:
1
#define TFT_FKT(x) tft_wr(INIT_SIZE - 1, x, 1 )
2
staticconstsize_tINIT_SIZE=sizeof(INIT);
die und das Array hinter "static" versteckt, das Ganze in eine separate
Übersetzungseinheit, nur noch die Funktion nach aussen sichtbar und
schon ist das wesentlich ungefährlicher.
Markus F. schrieb:> Jörg W. schrieb:>> Klar könnte man das in C++ alles viel schöner und eleganter schreiben.>> Das Beispiel braucht kein C++ um einigermassen wasserdicht zu werden.>> Statt das sizeof() ins Makro zu schreiben eine entsprechende Konstante> definiert:>>
1
>#defineTFT_FKT(x)tft_wr(INIT_SIZE-1,x,1)
2
>staticconstsize_tINIT_SIZE=sizeof(INIT);
3
>
>> die und das Array hinter "static" versteckt, das Ganze in eine separate> Übersetzungseinheit, nur noch die Funktion nach aussen sichtbar und> schon ist das wesentlich ungefährlicher.
Ok, wenn das Macro weg ist, habe ich sicher kein Problem mehr damit ;-)
Wenn die Signatur von tft_wr() so bleibt, habe ich aber nichts gewonnen.
Das Macro versuchte gerade, die Fehlermöglichkeiten der Schnittstelle zu
eliminieren, was aber nicht funktioniert. Jetzt haben wir es wieder mit
den zwei "zusammenhanglosen" Parametern zu tun ... oh, es sind sogar
drei Parameter, die eine semantische Einheit bilden.
Peter D. schrieb:> prog_uint8_t INIT[] => "\x1bTC\0" // text cursor off> "\x1b""DO\2" // rotate 180°> "\x1b""FD\x8\x1" // display color> "\x1b""FZ\x8\x1" // text color> "\x1b""DL" // display clear> "\x1b""YZ\x0" // no delay> "\x1b""YH\x64" // light on> ;
wo ist da eigentlich der Vorteil zu plain C?
Wilhelm M. schrieb:> Aber: wenn man so etwas (m.E. Murks) immer wieder hier postet, wird sich> an der Situation leider nichts ändern.
Es wird bestimmt ein riesen Geschütz in C++ geben, mit dem man das viel
eleganter erschlagen kann. Nur muß man das erst finden und auch
verstehen.
Ich wollte auch verdeutlichen, daß man Strings und Arrays nicht einfach
in einen Topf werfen kann. Für Arrays funktioniert strlen nicht mehr und
man muß sich eine andere Methode ausdenken, um die Länge zu ermitteln.
Peter D. schrieb:> Es wird bestimmt ein riesen Geschütz in C++ geben, mit dem man das viel> eleganter erschlagen kann. Nur muß man das erst finden und auch> verstehen.
Das "Geschütz" nennt sich dort einfach "Objekt" … man definiert sich
eine Klasse, die intern außer dem Bytehaufen auch noch die Länge als
Eigenschaft hat. Durch einen passenden Konstruktor kann man beim
Erzeugen eines Objekts (also einer Instanz dieser Klasse) dann einen
ganz normalen String als Initialisierer angeben.
Sehr wahrscheinlich gibt es sogar so eine Klasse schon irgendwie
irgendwo, andererseits ist das so einfach, dass man es als C++-Einstieg
durchaus auch als Fingerübung benutzen kann, das mal selbst zu zimmern.
Wobei textCursorOff () usw die einzelnen Befehle erzeugen, und combine
daraus ein Array macht. Kann ich aber gerade nicht vollständig
ausführen. Wäre so dann auch hübsch:
Peter D. schrieb:> Wilhelm M. schrieb:>> Aber: wenn man so etwas (m.E. Murks) immer wieder hier postet, wird sich>> an der Situation leider nichts ändern.>> Es wird bestimmt ein riesen Geschütz in C++ geben, mit dem man das viel> eleganter erschlagen kann. Nur muß man das erst finden und auch> verstehen.
So schlimm ist das ja eigentlich gar nicht. Allerdings ist der
Ausgangspunkt ,eine Kommandosequenz sei ein String, nicht gut.
Ein Kommando für dieses Display sind zwei Codes (Ascii-Zeichen) und dann
eine Payload. Die Kommandos können im Binär- oder Ascii-Modus gesendet
werden. Im Binär-Modus haben wir ein anderes Startbyte als im
Ascii-Modus, wo auch noch Trennzeichen gesendet werden sowie alles
dezimal codiert wird.
Daraus kann man erkennen, dass das Startbyte nicht zum Command gehört
und auch die Trennzeichen etc. erst durch die Realisierung des
Übertragungsmodus bestimmt werden.
Man könnte ein Kommando also einfach als Folge von Bytes darstellen:
1
std::array<std::byte,Size>command;
Allerdings ist das einzig Variable an einem festen Kommando die Payload,
deswegen kann man die zwei Codes des Kommandos auch gleich in den Typ
einbeziehen (und noch Bytes sparen):
Ob man das Kommando als std::array oder eigenes Template realisiert, man
hat es auf jedenfall mit unterschiedlichen Typen der Kommandos zu tun.
Deswegen kann man für eine Kommandosequenz keine homogenen Container
benutzen wie std::array<typ-der-commandos, anzahl>, sondern man braucht
einen heterogenen Container, etwa std::tuple:
Dabei ist natürlich lästig, die Länge der Payload explizit angeben zu
müssen und auch die explizite Typwandlung nach std::byte ist zwar gut,
aber sehr verbose.
Das geht dann mit einer Factory-Funktion einfacher:
1
template<charF,charS,typename...VV>
2
constexprautocommand(VV...vv){
3
returnCommand<F,S,sizeof...(VV)>(vv...);
4
}
Die Funktionen leitet die Länge ab und erzeugt die passenden
Parameterierung.
Also:
(Ein user-defined deduction-guide geht hier nicht wegen der expl.
Instanziierung durch die Kommando-Codes).
Jetzt ist noch das std::byte etwas lästig, dafür bieten sich
UDL-Operatoren an:
1
constexprstd::byteoperator""_B(charc){
2
returnstd::byte(c);
3
}
Nun kann man schreiben:
1
constexprautoinit_sequence=std::make_tuple(
2
command<'T','C'>(0_B,1_B),
3
command<'D','O'>(2_B)
4
);
Um die Sequenz ausgeben zu können:
1
template<typenameCommands>
2
voidtft_write(constCommands&commands){
3
std::apply([](auto...c){
4
// Assertion, das c den richtigen Typ hat, oder familiar-template syntax für diese lambda-expr (c++20)
5
// Ausgabe auf Ascii- oder Binär-Interface
6
},commands);
7
}
Dies geht dann mit jedem Container, der die Anforderungen von
std::apply<>() erfüllt.
Die Art des Inferfaces entscheidet dann über Start-Byte, Trennzeichen,
Prüfsumme, etc...
Wenn man sich noch etwas mehr Mühe gibt, kann man auch statisch prüfen,
ob die Kombination der beiden Ascii-Codes Sinn macht und ob die Payload
dazu passt. Wie gesagt: statisch. Bei einem Fehler würde das Programm
nicht compilieren! Man muss also zur Laufzeit dahingehend ggf. nichts
debuggen.
heißen, damit das String-Ende-'\0' nicht mit ausgegeben wird.
Im Prinzip gefällt mir deine Lösung gut, aber hundertprozentig
anfängertauglich ist auch sie nicht unbedingt:
Wilhelm kritisierte an Peters Lösung, dass damit folgendes nicht möglich
ist:
1
voidinit(uint8_t*s){
2
TFT_FKT(s);
3
}
4
5
intmain(){
6
init(INIT);
7
}
Möchte man das mit deiner Methode realisieren, muss auch init eine
Template-Funktion sein:
1
template<typenameT,std::size_tN>
2
inlinevoidinit(T(&arr)[N]){
3
tft_wr(arr);
4
// weiterer Initialisierungcode
5
// ...
6
}
Wird init mehrfach mit jeweils unterschiedlich langen Init-Strings
genutzt, wird dessen Code durch den Compiler jeweils dupliziert, was auf
den Mikrocontrollern, auf den sich Peter herumtreibt, insbesondere bei
sehr umfangreichem init-Code nicht erwünscht ist.
Wenn man sich des Problems bewusst ist, kann man es leicht umgehen. Wenn
der Programmierer aber dazu in der Lage ist, ist er kein blutiger
Anfänger mehr, so dass für ihn auch das von Wilhelm angeführte Problem
mit dem zum Zeiger zerfallenden Array keines darstellt.
Deswegen stellt sich für mich generell die Frage, wieviel Aufwand man in
zusätzlichem Quellcode man stecken sollte, um damit Programmierfehler zu
vermeiden, die nur mit sehr geringer Wahrscheinlichkeit passieren (in
dem Moment, wo man beginnt, nach einer Alternativlösung zu suchen, hat
man die Gefahr ja schon erkannt und wird deswegen nicht mehr in die
Falle tappen).
Dabei denke ich jetzt weniger an deine Lösung (die ja sehr kompakt und
relativ schnell hingeschrieben ist), sondern an Wilhelms Vorschläge, die
sich oft über zig Codezeilen erstrecken.
@Wilhelm:
Betrachte das, was ich hier schreibe, bitte nicht als generelle Kritik
an deiner Art und Weise zu programmieren. Ich kann aus deinen Beispielen
viel lernen, und ich werde viele deiner Vorschläge künftig auch in
meinem eigenen Code umsetzen, nur nicht unbedingt in so einfachen
Kontexten, wo ich befürchte, dass der Aufwand schnell mal den Nutzen
übersteigt.
Yalu X. schrieb:> Wird init mehrfach mit jeweils unterschiedlich langen Init-Strings> genutzt, wird dessen Code durch den Compiler jeweils dupliziert, was auf> den Mikrocontrollern, auf den sich Peter herumtreibt, insbesondere bei> sehr umfangreichem init-Code nicht erwünscht ist.
Das ist zwar grundsätzlich richtig, allerdings ist der Effekt in der
Praxis vernachlässigbar bzw. geht im Rauschen unter. Der Grund dafür
ist, dass das Compilerfrontend den template-code i.A: besser optimieren
kann (s.u.).
> @Wilhelm:>> Betrachte das, was ich hier schreibe, bitte nicht als generelle Kritik> an deiner Art und Weise zu programmieren. Ich kann aus deinen Beispielen> viel lernen, und ich werde viele deiner Vorschläge künftig auch in> meinem eigenen Code umsetzen, nur nicht unbedingt in so einfachen> Kontexten, wo ich befürchte, dass der Aufwand schnell mal den Nutzen> übersteigt.
Das kann jeder gerne so halten, wie er möchte. Ich kann dazu nur sagen,
dass wir seit Jahren genau diese Strategie verfolgen und damit wirklich
sehr erfolgreich sind. Der Code, den ich hier ab und zu mal poste bzw.
die Kommentare, die ich dazu abgebe, sind dann immer aus Sicht des
Library-Guys, also des Generalisten. Das kann man auch oben sehen, denn
es ist nun ganz leicht, einen Protokolladapter für das Ascii-Protokoll
oder einen für das Binärprotokoll des Displays dazwischen zu schieben,
was natürlich bei der alles-ist-ein-String-Variante nicht geht, die die
Grenzen zwischen den Kommandos und ihren Bestandteilen sind ja nicht
(statisch) sichtbar.
Grundsätzlich haben wir folgende Ziele:
* Header-Only Template Code
* Möglichst viele Fehler zur Compilezeit
* Permanentes Code-Refreshment auf Bibliotheksebene (full C++ feature
set)
Zwar ist AVR nicht unsere Zielplattform sondern SAM/ARM, aber auch dort
bleibt der allseits postulierte Code-Bloat aus.
Das wesentliche ist dem Compiler so viel statische Information wie
möglich mitzugeben bzw. die Datentypen optimal zu wählen: Werte sind
bedeutungslos, Datentypen sind alles. Die Vorteile dieser Strategie
scheinen evtl. Nachteile (etwa durch Mehrfachinstanziierungen)
auszugleichen, das zeigen jedenfalls exemplarische Untersuchungen, die
wir mal gemacht haben.
Wilhelm M. schrieb:>> Wird init mehrfach mit jeweils unterschiedlich langen Init-Strings>> genutzt, wird dessen Code durch den Compiler jeweils dupliziert, was auf>> den Mikrocontrollern, auf den sich Peter herumtreibt, insbesondere bei>> sehr umfangreichem init-Code nicht erwünscht ist.>> Das ist zwar grundsätzlich richtig, allerdings ist der Effekt in der> Praxis vernachlässigbar bzw. geht im Rauschen unter. Der Grund dafür> ist, dass das Compilerfrontend den template-code i.A: besser optimieren> kann (s.u.).
Das mag manchmal zutreffen, im gerade diskutieren Fall wird aber an den
Templates überhaupt nichts optimiert.
Ich habe Dr. Sommers Beispiel auf 4 Init-Strings erweitert, die
nacheinander alle durch einen Aufruf von init an das Display geschickt
werden. Um die stattfindende Code-Duplikation zu verdeutlichen, habe ich
in init ein paar Rechenoperationen angefügt.
test.cpp:
1
#include<stddef.h>
2
#include<stdint.h>
3
4
uint8_tINIT1[]="\x1b""A";
5
uint8_tINIT2[]="\x1b""BB";
6
uint8_tINIT3[]="\x1b""CCC";
7
uint8_tINIT4[]="\x1b""DDDD";
8
9
voidtft_wr(uint8_t*arr,size_tlength);
10
11
template<typenameT,size_tN>
12
inlinevoidtft_wr(T(&arr)[N]){
13
tft_wr(arr,N);
14
}
15
16
volatileuint32_ta,b,c,d;
17
18
template<typenameT,size_tN>
19
inlinevoidinit(T(&arr)[N]){
20
tft_wr(arr);
21
22
// relativ viel zusätzlicher Code
23
a=b+c;d=a+b;c=d+a;b=c+d;
24
a=b+c;d=a+b;c=d+a;b=c+d;
25
}
26
27
intmain(){
28
init(INIT1);
29
init(INIT2);
30
init(INIT3);
31
init(INIT4);
32
}
Diesen Code habe ich für einen AVR kompiliert und mir die Größe der
erzeugten Objektdatei ausgeben lassen:
1
avr-gcc -mmcu=atmega8 -std=c++17 -Os -c test.cpp
2
avr-size test.o
Die Größe der text-Section ist mit einem einzelnen init-Aufruf
468 Bytes,
mit allen 4 Aufrufen
1854 Bytes,
also fast das Vierfache. Der Compiler erzeugt tatsächlich 4 Instanzen
der Template-Funktion, deren Assembler-Code jeweils 132 Instruktionen
lang ist und sich nur in einer einzigen Instruktion von den anderen
Instanzen unterscheidet.
Diesen schon sehr deutlichen Zuwachs der Codegröße kann man in diesem
Beispiel vermeiden, indem man den von den Template-Parametern
unabhängigen Teil der init-Funktion in eine separate Funktion auslagert.
Dazu muss man sich aber erst einmal des Problems bewusst werden und darf
nicht zu sehr auf die Optimierungsfähigkeiten des Compilers hoffen.
Yalu X. schrieb:> Die Größe der text-Section ist mit einem einzelnen init-Aufruf>> 468 Bytes,>> mit allen 4 Aufrufen>> 1854 Bytes,>> also fast das Vierfache. Der Compiler erzeugt tatsächlich 4 Instanzen> der Template-Funktion, deren Assembler-Code jeweils 132 Instruktionen> lang ist und sich nur in einer einzigen Instruktion von den anderen> Instanzen unterscheidet.
Auch wenn init static, also "wirklich nur hier gebraucht", ist bzw. LTO
benutzt wird?
Gerade getestet:
- gcc8.1
- "static" vor allen Funktionen (außer Main) oder LTO,
- O3
-> 586 Bytes .text
> Diesen schon sehr deutlichen Zuwachs der Codegröße kann man in diesem> Beispiel vermeiden, indem man den von den Template-Parametern> unabhängigen Teil der init-Funktion in eine separate Funktion auslagert.> Dazu muss man sich aber erst einmal des Problems bewusst werden und darf> nicht zu sehr auf die Optimierungsfähigkeiten des Compilers hoffen.
Doch, darf man!
Man muß ihm nur die nötige Info mitgeben, z.B. daß Funktionen niemals
von außerhalb gerufen werden.
Oder eben über den"Trick" LTO, dann bekommt er das selber raus.
PS: einmal init -> 576 Bytes, ergo: kein Bloat!
Carl D. schrieb:> Auch wenn init static, also "wirklich nur hier gebraucht", ist bzw. LTO> benutzt wird?
Bei mir ändert sich die Codegröße dadurch nur marginal.
Carl D. schrieb:> - "static" vor allen Funktionen (außer Main) oder LTO,
Was machst du mit
1
voidtft_wr(uint8_t*arr,size_tlength);
?
Ich bin davon ausgegangen, dass das eine externe Bibliotheksfunktion
ist. Wenn du sie ebenfalls static machen möchtest, musst du natürlich
dafür sorgen, dass sie irgendetwas mit dem Argument length anstellt,
bspw. so:
1
staticvoidtft_wr(uint8_t*arr,size_tlength){
2
volatilesize_tdummy=length;
3
}
Sonst unterscheiden sich die 4 Template-Instanzen nicht voneinander und
können durch den Compiler zu einer einzigen zusammengefasst werden.
Carl D. schrieb:>> Dazu muss man sich aber erst einmal des Problems bewusst werden und darf>> nicht zu sehr auf die Optimierungsfähigkeiten des Compilers hoffen.> Doch, darf man!> Man muß ihm nur die nötige Info mitgeben, z.B. daß Funktionen niemals> von außerhalb gerufen werden.
Mal anders argumentiert: Die Größe des Arrays ist in dem einen Fall ein
Datum, mit dem ein Algorithmus arbeitet, in dem anderen Fall ein
Parameter des Algorithmus selbst.
und
kann man sicher so definieren, dass sie das selbe Ergebnis liefern. Aber
in dem einen Fall ist die 35 ein Argument einer Funktion die somit
allgemeiner anzuwenden ist.
Das wird bei den Beispielen hier schon dann deutlich, wenn man mal
versucht eine unbestimmte Menge von Kommandos aus einer Datei
einzulesen...
Yalu X. schrieb:> Ich habe Dr. Sommers Beispiel auf 4 Init-Strings erweitert, die> nacheinander alle durch einen Aufruf von init an das Display geschickt> werden. Um die stattfindende Code-Duplikation zu verdeutlichen, habe ich> in init ein paar Rechenoperationen angefügt.
Du hast ein Beispiel konstruiert(!), was natürlich eine starke
Vermehrung des Maschinencodes bewirkt. Dies ist allerdings durch die
volatile Qualifizierung im template entstanden. Dies entspricht
allerdings nicht der Praxis.
In der Praxis haben wir SFRs, die notwendigerweise volatile qualifiziert
sind, oder (ganz wenige) Datenstrukturen, die nebenläufig verwendet
werden, und deswegen volatile sind.
Jetzt komme ich mit einem etwas praxisrelevanteren Beispiel: wir wollen
die Daten der Arrays durch ein Protokoll laufen lassen und dann auf
irgendeiner Schnittstelle ausgeben. Die Schnittstelle ist hier einfach
mal als ein SFR dargestellt. Natürlich soll das ganze ein bisschen
modular sein: unterschiedliche Protokolle mit unterschiedlichen
Schnittstellen kombinierbar.
Variante A in C:
main.c:
Da bekomme ich für das Target atmega328:
C: 238 Bytes text, 7 Bytes bss
C++: 188 Bytes text, 7 Bytes bss
Wenn ich für die C-Variante LTO einschalte:
C: 198 Bytes text, 7 Bytes bss
Soweit zu Beispielen (frei nach Pipi Langstrumpf!).
Hinzu kommt m.E. der besser strukturierte und sicherere Code. Wenn man
das Beispiel erweitert auf:
1
usingspi1=Spi<0>;
2
usingspi2=Spi<1>;
3
usingp1=Protocol<A,spi1>;
4
usingp2=Protocol<A,spi2>;
5
6
std::array<std::byte,2>a1;
7
std::array<std::byte,4>a2;
8
std::array<std::byte,8>a3;
9
std::array<std::byte,16>a4;
10
11
intmain(){
12
p1::put(a1);
13
p1::put(a2);
14
p2::put(a3);
15
p2::put(a4);
16
}
bzw.:
1
voidspi1_put(uint8_tdata);
2
voidspi2_put(uint8_tdata);
3
4
uint8_ta1[2];
5
uint8_ta2[4];
6
uint8_ta3[8];
7
uint8_ta4[16];
8
9
intmain(){
10
protocol_A(a1,sizeof(a1),spi1_put);
11
protocol_A(a2,sizeof(a2),spi1_put);
12
protocol_A(a3,sizeof(a3),spi2_put);
13
protocol_A(a4,sizeof(a4),spi2_put);
14
}
so haben wir (mit LTO für C):
C: 272 Bytes text, 32 Bytes bss
C++: 224 Bytes text, 32 Bytes bss
Also hier sehen wir nichts von Code-Bloat, im Gegenteil.
Wilhelm M. schrieb:> Yalu X. schrieb:>>> Ich habe Dr. Sommers Beispiel auf 4 Init-Strings erweitert, die>> nacheinander alle durch einen Aufruf von init an das Display geschickt>> werden. Um die stattfindende Code-Duplikation zu verdeutlichen, habe ich>> in init ein paar Rechenoperationen angefügt.>> Du hast ein Beispiel konstruiert(!), was natürlich eine starke> Vermehrung des Maschinencodes bewirkt. Dies ist allerdings durch die> volatile Qualifizierung im template entstanden. Dies entspricht> allerdings nicht der Praxis.
Konstruiert ist nur dieser Teil als Beispiel für einen etwas größeren
Codeabschnitt:
1
volatileuint32_ta,b,c,d;
2
3
...
4
// relativ viel zusätzlicher Code
5
a=b+c;d=a+b;c=d+a;b=c+d;
6
a=b+c;d=a+b;c=d+a;b=c+d;
Ersetze ihn durch irgendwelchen sinnvollen, ähnlich großen Code, der
frei von volatiles ist, und du wirst feststellen, dass er immer noch für
jeden init-Aufruf dupliziert wird.
Wie ich oben geschrieben habe, kann das Problem dadurch behoben werden,
dass der gemeinsame, von den Template-Parameter unabhängige Code in eine
separate Funktion ausgelagert werden.
Fakt ist aber dass diese Optimierung durch den Programmierer geschehen
muss, der Compiler ist dazu (noch) nicht in der Lage.
> Jetzt komme ich mit einem etwas praxisrelevanteren Beispiel: wir wollen> die Daten der Arrays durch ein Protokoll laufen lassen und dann auf> irgendeiner Schnittstelle ausgeben.
Ich schrieb ja nicht, dass der Code-Bloat immer auftritt. In deinem
Beispiel tritt das Problem deswegen nicht in Erscheinung, weil die
put-Funktionen sehr klein sind. Sobald diese Funktionen etwas mehr tun
als nur ein paar Bytes zu kopieren, wirst du auch hier die
Codeduplizierung bemerken.
Yalu X. schrieb:> Ersetze ihn durch irgendwelchen sinnvollen, ähnlich großen Code, der> frei von volatiles ist, und du wirst feststellen, dass er immer noch für> jeden init-Aufruf dupliziert wird.
Das stimmt auf der einen Seite, auf der anderen Seite entstehen durch
den Template-Code größere Optimierungspotentiale (sowohl durch den
Compiler wie auch im Algorithmus selbst) wie oben schon gesagt.
Vielleicht wird es deutlich, warum in Summe kein Code-Bloat auftritt,
wenn wir unser Protokoll für längere Folgen erweitern und fügen eine
Summe hinzu: