Gast
#5994603
Wenn ich sowas schreibe, kriege ich keine Warnung. Ist das so gewollt?
1 | |
2 | |
3 | |
4 | |
Welcher Kommandozeilenparameter muss angegeben werden, damit eine Warnung erscheint?
|
Anzeige
|
avr-gcc: Warnung bei fehlendem Cast aktivieren?
Gast
#5994603
Wenn ich sowas schreibe, kriege ich keine Warnung. Ist das so gewollt?
Welcher Kommandozeilenparameter muss angegeben werden, damit eine Warnung erscheint?
Gast
#5994624
Anders gefragt. Warum erwartest du eine Warnung?
Gast
#5994625
Lass einmal die for weg. Erwartest du auch hierbei eine Warnung? uint32_t var = 88
Gast
#5994631
Name schrieb: > Anders gefragt. Warum erwartest du eine Warnung? Ggf. ist int nur 16 Bit groß, dann wäre der Code so fehlerhaft.
Gast
#5994643
Ist so gewollt, da mit -Wsign-conversion zu viele Meldungen kommen ;-) Name schrieb: > Anders gefragt. Warum erwartest du eine Warnung? Ich vermute, es geht darum, dass 1 und damit auch 1 << i vom Typ int ist. Man müsste eigentlich UINT32_C(1) << i schreiben. Bei einem 32-Bit-int führt 1 << 31 zu undefiniertem Verhalten. Beim AVR ist int sogar nur 16 Bit breit.
Gast
#5994659
> Bei einem 32-Bit-int führt 1 << 31 zu undefiniertem Verhalten.
Ist nicht sogar jeglicher left-shift eines signed Typen undefiniert?
Eine gcc-Warn-Option dafür ist mir aber nicht bekannt (wäre wohl noch
unpopulärer als -Wsign-conversion ;-) ).
foobar schrieb: >> Bei einem 32-Bit-int führt 1 << 31 zu undefiniertem Verhalten. > > Ist nicht sogar jeglicher left-shift eines signed Typen undefiniert? Nein, nur wenn der zu schiebende Wert negativ ist oder das Ergebnis der entsprechenden Multiplikation mit 2ᶦ vom Typ nicht repräsentiert werden kann. Jemand schrieb: > Name schrieb: >> Anders gefragt. Warum erwartest du eine Warnung? > > Ggf. ist int nur 16 Bit groß, dann wäre der Code so fehlerhaft. Beim avr-gcc ist das so. Oliver
Gast
#5994703
Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es doch eine Warnung geben...
Gast
#5994708
Manfred schrieb: > Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es > doch eine Warnung geben... Da müsste der gcc aber schon sehr clever sein um hier das Problem zu sehen. Kann man so etwas heutzutage erwarten? Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen. D.h. wenn man mit Bits rummacht sollte man generell wissen was für Datentypen man da benutzt. test schrieb: > Kann man so etwas heutzutage erwarten? > > Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen. Darüber kann man gespaltener Meinung sein. Es gibt auch die Theorie derzufolge es das Ziel sein sollte eine Sprache (oder in Ermangelung einer neuen Sprache dann halt eben einen Compiler für eine existierende) so zu entwerfen daß der Programmierer bestimmte (möglichst viele) Arten von Fehlern schlichtweg einfach nicht mehr machen kann da man mittlerweile gelernt hat daß menschliche Programmierer zwar unglaublich clevere Algorithmen ersinnen können aber dennoch immer wieder so blöde kleine Flüchtigkeitsfehler machen. Das resoniert auch gut mit der Utopie daß eigentlich die Maschinen dem Menschen dienen sollen und nicht umgekehrt.
Gast
#5994730
Schaut euch mal die ersten Kommentare an. Ich hatte meine Frage bewusst schwammig formuliert, um zu demonstrieren, wie leicht man hier den Fehler übersehen kann. Der Compiler ist schon recht schlau. Wenn ich ein Array einbaue, mit Größe 31 und das in der Schleife befülle, kommt ja auch sofort eine Warnung.
test schrieb: > Manfred schrieb: >> Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es >> doch eine Warnung geben... > > Da müsste der gcc aber schon sehr clever sein um hier das Problem zu > sehen. Der Compiler müsste etwas Code-Analyse betreiben. Wenn man die Zeile
für sich betrachtet, ist da erstmal nichts falsch dran. Eine 1 wird um eine variable Anzahl von Bits geschoben. Solange man den Wert von i nicht kennt, ist eine Warnung nicht gerechtfertigt. Jetzt ist es an der Stelle aber nicht übermäßig schwer für den Compiler, zu wissen, mit welchen Werten von i dieser Code definitiv ausgeführt werden wird. Der Optimizer analysiert solche Schleifen sowieso, um z.B. loop-unrolling betreiben zu können. Von daher könnte er hier schon merken, dass der Code definitiv fehlerhaft ist. > Kann man so etwas heutzutage erwarten? > > Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen. Heutzutage ist es aber Aufgabe des Compilers, nicht nur das Programm einfach stur in Maschinencode zu übersetzen, wenn das irgendwie geht, sondern auch, dem Programmierer zu helfen, Fehler zu vermeiden. Er übernimmt heute auch die Rolle eines Lint-Tools. > D.h. wenn man mit Bits rummacht sollte man generell wissen was für > Datentypen man da benutzt. Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch schnell mal einen Flüchtigkeitsfehler.
Gast
#5994782
Rolf M. schrieb: > Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch > schnell mal einen Flüchtigkeitsfehler. Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab) nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-) Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in Char Arrays gesammelt werden... test schrieb: > Rolf M. schrieb: >> Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch >> schnell mal einen Flüchtigkeitsfehler. > > Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch > nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab) > nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-) Ein uint32_t hat auf jeder Plattform 32-Bit. Ein int/unsigned int hat mindestens 16-Bit. test schrieb: > Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch > nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab) > nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-) Ich weiß nicht, wie du auf den Quatsch kommst. Das ist jedenfalls falsch. > Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt > es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur > keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in > Char Arrays gesammelt werden... Sollte unsigned char sein. test schrieb: > Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt > es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur > keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in > Char Arrays gesammelt werden... Das machen nur C-Programmierer. In C++ nimmt man std::byte.
Gast
#5996106
Das könnte man wahrscheinlich mit ubsan finden. https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ MaWin schrieb: > Das könnte man wahrscheinlich mit ubsan finden. > https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ Geht das mit bare-metal targets auch (denn im OP ist von avr-gcc die Rede)?
Gast
#5996152
Bernd K. schrieb: > Geht das mit bare-metal targets auch (denn im OP ist von avr-gcc die > Rede)? Theoretisch schon. Ich weiß nicht, ob avr-libc da Unterstützung hat (libubsan). Vermutlich aber eher nicht. Noch ein Antwort, weil es mir gerade über die Füße lief: der UB-sanititer ist in C++ programmiert und benutzt die libstdc++. Da aber für das AVR target keine libstdc++ existiert, wird im configure des avr-gcc die lubsan deaktiviert. Genau genommen gibt's die Libs schon; sowohl libstdc++-v3 als auch libsupc++, wobei letztere Teil der libstdc++-v3 ist und den rudimentären C++ Support bereitstellt wie z.B. new und new[]. Müsste halt mal jemand die handvoll Anpassungen für AVR machen. Vorgesehen ist das, müsste nur noch ausgefüllt werden. Die Sanitizer wollen aber noch mehr als libstdc++v3. Aus libsanitizer/configure.ac:
Will also auch POSIX. test schrieb: > vermutlich gibt es geeignete Datentypen und Arten vernünftig zu > programmieren. Macht nur keiner ;-) > Ich meine wenn ich sehe das heutzutage immer noch Bytes in > Char Arrays gesammelt werden... Ja, ist leider immer noch sehr verbreitet. Seit C99 gibt es die stdint.h und stdbool.h (daraus kommt der schon erwähnte uint32_t). Damit ist es für einen Programmierer möglich seine Algorithmen so zu schreiben, dass sie Chance haben einen Plattformwechsel zu überleben und gibt auch den Tools mehr Chance für hilfreiche Warnungen. Wird aus meiner Sicht zu wenig geschult bzw. ist zu selten Bestandteil der Firmen Coding-Guidelines. test schrieb: > Da müsste der gcc aber schon sehr clever sein um hier das Problem zu > sehen. Kann man so etwas heutzutage erwarten? Ja. test schrieb: > Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen. > D.h. wenn man mit Bits rummacht sollte man generell wissen was für > Datentypen man da benutzt. Ja. Darum sollten auch anständig definierte Datentypen (wie z. B. aus stdint.h) verwendet werden. So ist gleichzeitig auch der Code besser dokumentiert ohne Mehraufwand. Rolf M. schrieb: > Er übernimmt heute auch die Rolle eines Lint-Tools. Ein heutiger Compiler soll heutzutage viele Prüfungen eines Linters (Statisches Codeanalyse Werkzeug) übernehmen, so weit wie er das halt kann. Zusätzlich kann der Compiler Dinge prüfen, die abhängig von der Zielplattform sind, was nicht in den Bereich eines Linters passt. Da dazu noch keine Namen genannt wurden, hier zwei OpenSource Linter für C/C++: http://splint.org/ http://cppcheck.sourceforge.net/ Spielt mal damit herum, ist sehr spannend was die Tools so finden können. Hatte mir mal in einem Firmenprojekt (durfte ein Projekt von einem Kollegen übernehmen) massiv Zeit eingespart. Christoph Z. schrieb: > http://splint.org/ Splint Release 3.1.2 12 July 2007 Wer mit Compilern unterwegs ist oder sein muß, die auch aus dieser Zeit stammen, für den mag sowas hilfreich sein. Aktuelle Compiler können bzgl. statischer Codeanalyse inzwischen sehr viel mehr. Oliver Wilhelm M. schrieb: > Das machen nur C-Programmierer. In C++ nimmt man std::byte. Das is ein Ding. ;-O Was ist denn jetzt besser für Geschwindigkeit, Sicherheit und Größe? Bit Funktionen als Makro / Inline zu schreiben oder die Byte-Klasse zu nehmen? mfg Oliver S. schrieb: > Christoph Z. schrieb: >> http://splint.org/ > > Splint Release 3.1.2 > 12 July 2007 > > Wer mit Compilern unterwegs ist oder sein muß, die auch aus dieser Zeit > stammen, für den mag sowas hilfreich sein. > > Aktuelle Compiler können bzgl. statischer Codeanalyse inzwischen sehr > viel mehr. Ist zwar kein Compiler aber https://clang.llvm.org/extra/clang-tidy/ sollte auch nicht im eigenen Werkzeugkasten fehlen. Matthias Dazu alle verfügbaren sanitizer, dazu valgrind. Das sind dann zwar nicht nur statische, sondern auch run-time-Analysen, hilft aber trotzdem. Oliver Und verschiedene Compiler in möglichst aktueller Version. gcc und clang finden viel und viel unterschiedliches. Und da wir hier bei µC.net sind: Die "Geschäftslogik" einer Anwendung sollte sich nicht nur für den µC übersetzen lassen. Denn nur so kann man die Laufzeitchecker (asan, ubsan, valgrind) richtig einsetzen. Matthias Der TO wollte sicher keine Laufzeitlösung mit sanitizern, etc., sondern eine Compilezeitlösung für sein Problem. Abgesehen davon, dass es "richtiger" wäre zu schreiben
liegt die Wurzel des Übels aber an anderer Stelle: - eine Ganzzahl vom Type uint32_t wird als Bitmaske missbraucht - der Datentyp für den Bit-Shift (uint8_t) steht in keiner Relation zu dem Typ der Bitmaske Eine simple Laufzeitlösung wäre korrekterweise folgendes:
Das schreibt zwar so keiner hin, wäre aber der korrekte Ansatz, denn der gültige Wertebereich für den BitShift kann durch den Datentyp uint8_t nicht eingehalten werden. Also trägt der Programmierer die Verantwortung das zuzusichern: eine klassische Vorbedingung. Für eine "richtige" Lösung braucht man - einen (generischen) Datentyp (etwa: mask_t<>) für eine Bitmaske mit N Bits - einen Shiftoperator für mask_t<>, - einen ganzzahligen Datentyp, der nur den Wertebereich des Shifts der Maske abdeckt. Damit hätten wir eine Lösung der Form:
Die obigen Fehlerquellen sind ausgeschlossen. Ist nicht schwer umzusetzen (std::byte ist da nur ein erster Schritt in diese Richtung), genauso wie etwa bounded_integer (ein ganzzahliger Datentyp mit beliebigen Grenzen und einstellbarer overrun-policy). Das lässt sich mal wieder in das Thema strong types einordnen bzw. "Die eingebauten Datentypen sind dazu da, nicht benutzt zu werden".
Gast
#6130344
Wilhelm M. schrieb: > Das lässt sich mal wieder in das Thema strong types einordnen bzw. "Die > eingebauten Datentypen sind dazu da, nicht benutzt zu werden". Genau so ist es.
Gast
#6130357
in diesem Falle hilft eine statische code analyse wie z.B. cppcheck, hier eine onlinedemo http://cppcheck.sourceforge.net/demo/ nur malso schrieb: > in diesem Falle hilft eine statische code analyse cppcheck --enable=all findet das Problem nicht ...
Gast
#6130365
also bei mir führt (in der onlinedemo)
zu folgender Ausgabe
Hier aber wieder nicht:
Ohne zusätzliche Tools schreibt man seine Tests einfach in constexpr-Kontexte, und alles UB wird erkannt. Wilhelm M. schrieb: > Hier aber wieder nicht: Wenn du das (an der Stelle) fürchterliche i{} durch ein übliches i=0 ersetzt, dann doch. Oliver Oliver S. schrieb: > Wilhelm M. schrieb: >> Hier aber wieder nicht: > > Wenn du das (an der Stelle) fürchterliche i{} durch ein übliches i=0 > ersetzt, dann doch. Ich finde es sehr praktisch und gar nicht fürchterlich. Das ist uniform-initialization-syntax seit C++11 und cppcheck sollte das so langsam mal mitbekommen haben. Dies zeigt aber das grundsätzliche Problem bei der Verwendung externer Werkzeuge. Wilhelm M. schrieb: > Dies zeigt aber das grundsätzliche Problem bei der Verwendung externer > Werkzeuge. Stimmt, deswegen schreibe ich inzwischen auch wieder
statt
obwohl letzteres natürlich viel cooler ist ;-)
Beitrag #6130982 wurde von einem Moderator gelöscht.
Wilhelm M. schrieb: > Oliver S. schrieb: >> Wilhelm M. schrieb: >>> Hier aber wieder nicht: >> >> Wenn du das (an der Stelle) fürchterliche i{} durch ein übliches i=0 >> ersetzt, dann doch. > > Ich finde es sehr praktisch und gar nicht fürchterlich. Ich finde, dass man den Wert, den man da in den Integer rein schreibt, durchaus sehen sollte, und das nicht nur, wenn er von 0 verschieden ist. Yalu X. schrieb: > Stimmt, deswegen schreibe ich inzwischen auch wieder > if (x < 0) ... ... würde ich jetzt bei std::is_same_v<decltype(x), std::string> == true nicht machen. Wilhelm M. schrieb: > Das ist uniform-initialization-syntax seit C++11 und cppcheck sollte das > so langsam mal mitbekommen haben. Sorry, schon seit C++03. Rolf M. schrieb: > Ich finde, dass man den Wert, den man da in den Integer rein schreibt, > durchaus sehen sollte, und das nicht nur, wenn er von 0 verschieden ist. Nennt sich value-initialization und ist in der generischen Programmierung sehr praktisch. Aber selbst mit dem redundanten bzw. manchmal nicht möglichem Initialwert (hier bspw: 0) findet cppcheck das Problem nicht. Wilhelm M. schrieb: > Rolf M. schrieb: >> Ich finde, dass man den Wert, den man da in den Integer rein schreibt, >> durchaus sehen sollte, und das nicht nur, wenn er von 0 verschieden ist. > > Nennt sich value-initialization und ist in der generischen > Programmierung sehr praktisch. Mir ist schon bewusst, dass das praktisch sein kann. An dieser Stelle ist es aber fehl am Platz. Hier haben wir auch keine generische Programmierung, sondern eine ganz simple Zählschleife, deren Zähler am Anfang mit einem Wert vorbelegt wird. Und den Wert an dieser Stelle nur deshalb zu verstecken, weil er zufälligerweise mit dem dem Default für die Initialisierung übereinstimmt, finde ich nicht sinnvoll. Man muss nicht jedes Feature überall nutzen, nur weil's halt geht. > Aber selbst mit dem redundanten bzw. manchmal nicht möglichem > Initialwert (hier bspw: 0) findet cppcheck das Problem nicht. Das ist ein anderes Problem. Rolf M. schrieb: > Hier haben wir auch keine generische > Programmierung, sondern eine ganz simple Zählschleife, deren Zähler am > Anfang mit einem Wert vorbelegt wird. Warum sollte man da einen Unterschied machen? Initialisierung immer mit {} und man muss sich nicht umstellen. Rolf M. schrieb: > weil er zufälligerweise mit dem dem Default für > die Initialisierung übereinstimmt, Zufällig ist hier nichts. Rolf M. schrieb: >> Aber selbst mit dem redundanten bzw. manchmal nicht möglichem >> Initialwert (hier bspw: 0) findet cppcheck das Problem nicht. > > Das ist ein anderes Problem. Sicher. Bedeutet aber, dass mir cppcheck nichts bringt. Wie schon oben erläutert, halte ich das Vorgehen des TO bzw. das "übliche" Vorgehen für falsch. Man kann es aber recht einfach lösen. Für eine Laufzeitlösung s.o. und eine Compilezeit-Lösung ist auch einfach:
BTW: std::bitmask löst zwar das Vokabularproblem, aber hat sonst die übliche Semantik bzw. Möglichkeiten. Wilhelm M. schrieb: > Nennt sich value-initialization und ist in der generischen > Programmierung sehr praktisch. Da gehört das auch hin, in eine for-Schleife mit int aber nicht. Allerdings ist das hier alles OT, für das Thema gibt ja einen eigenen Thread (in dem schon alles gesagt wurde). Oliver Oliver S. schrieb: > Da gehört das auch hin, in eine for-Schleife mit int aber nicht. Dein Argument ist: weil es immer so war, soll es so bleiben. Mein Argument ist: Vereinheitlichung und damit Vereinfachung der Notation. Wilhelm M. schrieb: > Mein Argument ist: Vereinheitlichung und damit Vereinfachung der > Notation. Meine Kritik (und wohl auch die anderer Diskussionsteilnehmer hier) bezieht sich nicht primär auf die Verwendung der geschweiften Klammern¹, sondern auf das Weglassen der 0. Einheitlich wäre es deswegen, wenn man wie bei
auch beim Start mit 0 den Startwert explizit hinschreibt, also so:
und nicht so:
Ich bin ja prinzipiell auch ein Freund knapper Schreibweisen, aber nur dann, wenn man sie auch halbwegs durchgängig verwenden kann. Warum sollte man bei den 4294967296 möglichden Initialisierungswerten für ein int in einem einzigen Fall (nämlich für die 0) eine andere Schreibweise verwenden? Bei der generischen Programmierung sieht das natürlich anders aus. Dort stehen die leeren geschweiften Klammern i.Allg. nicht für die numerische Null, sondern für das neutrale Element eines Monoiden. Da dieses Element etwas ganz Besonderes ist, darf auch seine Initialisierung etwas anders aussehen. ――――――――――――― ¹) Dennoch empfinde ich sie als häßlich, weil sie keinerlei Bezug nur mathematischen Notation haben, wo eine Variablenbelegung immer und unabhängig vom Typ mit einem Gleichheitszeichen erfolgt. Yalu X. schrieb: > Wilhelm M. schrieb: >> Mein Argument ist: Vereinheitlichung und damit Vereinfachung der >> Notation. > > Meine Kritik (und wohl auch die anderer Diskussionsteilnehmer hier) > bezieht sich nicht primär auf die Verwendung der geschweiften Klammern¹, > sondern auf das Weglassen der 0. Ja, zumindest meine auch. Daher passt diese Frage eigentlich genau dazu: Wilhelm M. schrieb: > Warum sollte man da einen Unterschied machen? Genau das ist eben auch mein Gedanke: Warum sollte man einen Unterschied machen, ob die Schleife jetzt bei 0 oder z.B. bei 42 beginnt? Yalu X. schrieb: > Einheitlich wäre es deswegen, wenn man wie bei > auch beim Start mit 0 den Startwert explizit hinschreibt, also so: Meine Aussage bezieht sich nicht (nur) auf die Schreibweise, sondern eben auf die Semantik:
Im Beispiel oben sieht man eben den Unterschied: ggf. ist es für einen Datentyp T gar nicht möglich. Die geringste implizite template-Typanforderung ist die default-Konstruktion über die value-initialization. Und bei primitiven DT resultiert zero-initialization. Das ist ganz eindeutig und klar. Yalu X. schrieb: > Dennoch empfinde ich sie als häßlich, weil sie keinerlei Bezug nur > mathematischen Notation haben, wo eine Variablenbelegung immer und > unabhängig vom Typ mit einem Gleichheitszeichen erfolgt. Mathematische Variablen und benannte Objekte aka Variablen im Kontext einer imperativen Programmiersprache sind zwei unterschiedliche Dinge. Wilhelm M. schrieb: > Im Beispiel oben sieht man eben den Unterschied: ggf. ist es für einen > Datentyp T gar nicht möglich. Das ist aber genau der Punkt. Wilhelm M. schrieb: > for(uint8_t i{}; i < 33; i++) { Da gibt es kein T und keine semantisch erforderliche default-Initialisierung. Da steht ein POD uint8_t, und dessen Semantik ist "Startwert der Schleifenvariablen". Da nicht die 0 hinzuschreiben, geht am Ziel vorbei. Oliver Wilhelm M. schrieb: > T v1{}; // value-initialization: non-class type -> zero-initialization > T v2{0}; // direct-initialization: non-class type -> no narrowing; > class-type -> need ctor callable with Und was spricht jetzt genau dagegen, für die Laufvariable mit dem festen Typ uint8_t die direct-initialization statt der value-initialization zu verwenden? Das kostet zwar einen Tastendruck mehr, dafür hätten aber alle Zählschleifen unabhängig von ihrem Startwert ein einheitliches Aussehen, und Vereinheitlichung scheint ja auch dir wichtig zu sein: Wilhelm M. schrieb: > Mein Argument ist: Vereinheitlichung und damit Vereinfachung der > Notation. Wilhelm M. schrieb: > Im Beispiel oben sieht man eben den Unterschied: ggf. ist es für einen > Datentyp T gar nicht möglich. Die geringste implizite > template-Typanforderung ist die default-Konstruktion über die > value-initialization. Dass die value-initialization in der generischen Programmierung sinnvoll sein kann, habe ich ja oben bereits geschrieben. Im konkreten Beispiel mit der Schleife ist aber nichts generisch, sondern wir haben es mit einem klar festgelegten Typ (uint8_t) zu tun. Wilhelm M. schrieb: > Yalu X. schrieb: >> Dennoch empfinde ich sie als häßlich, weil sie keinerlei Bezug nur >> mathematischen Notation haben, wo eine Variablenbelegung immer und >> unabhängig vom Typ mit einem Gleichheitszeichen erfolgt. > > Mathematische Variablen und benannte Objekte aka Variablen im Kontext > einer imperativen Programmiersprache sind zwei unterschiedliche Dinge. Das ist klar. Trotzdem finde ich es praktisch, wenn sich die Syntax einer Programmiersprache an bereits bekannte Schreibweisen anlehnt, die bspw. von - der natürlichen Sprache (wie bspw. bei "if", "while" und "return"), - der Mathematik (wie bspw. "+", "-", "sin") oder - anderen bereits verbreiteten Programmiersprachen übernommen werden können. In den allermeisten Programmiersprachen (insbesondere auch den imperativen) wird nun mal mit einem Gleichheitszeichen initialisiert. Nur C++ entfernt sich immer mehr von dieser Konvention.
Gast
#6133365
Yalu X. schrieb: > Wilhelm M. schrieb: >> Im Beispiel oben sieht man eben den Unterschied: ggf. ist es für einen >> Datentyp T gar nicht möglich. Die geringste implizite >> template-Typanforderung ist die default-Konstruktion über die >> value-initialization. > > Dass die value-initialization in der generischen Programmierung sinnvoll > sein kann, habe ich ja oben bereits geschrieben. Im konkreten Beispiel > mit der Schleife ist aber nichts generisch, sondern wir haben es mit > einem klar festgelegten Typ (uint8_t) zu tun. Wobei das hier nicht mal eine Rolle spielt. Selbst wenn es generisch wäre: Wenn ich eine Zählschleife habe und die explizit bei 0 starten lassen will, schreibe ich 0 als Startwert hin, egal von welchem Typ mein Zähler ist. Und ich schreibe den Wert hin, egal ob er 0 oder 1 oder 11149 ist. Die Semantik ist eben "ich möchte bei 0 anfangen zu zählen" und nicht "ich möchte bei dem default-Wert des Datentyps anfangen". Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|