Wilhelm M. schrieb im Beitrag "Re: avr-gcc: direkter Register Zugriff vs structure-mapping und fehlende Optimierung?" > In C++ benutze ich schon immer ein structure-mapping mit > eingenen Register-Typen, so dass auch nur die richtigen > Flags für die Register benutzt werden können, ansonsten > Compile-Zeit-Fehler Könnte man das in C ohne ++ auch haben? Etwas ähnliches erreicht man wohl mit Bitfeldern in der struct, aber das ist umständlich, wenn man mehrere Bits gleichzeitig setzen muss.
Bauform B. schrieb: > Wilhelm M. schrieb im > Beitrag "Re: avr-gcc: direkter Register Zugriff vs structure-mapping und fehlende Optimierung?" > >> In C++ benutze ich schon immer ein structure-mapping mit >> eingenen Register-Typen, so dass auch nur die richtigen >> Flags für die Register benutzt werden können, ansonsten >> Compile-Zeit-Fehler > > Könnte man das in C ohne ++ auch haben? Was hindert Dich denn daran, C++ zu benutzen?
Ein T. schrieb: > Was hindert Dich denn daran, C++ zu benutzen? Lustig, daß es für diese einfache Frage gleich vier negative Bewertungen, aber nur eine positive gibt., obwohl die Verwendung von C++ sich zunächst nur in der Nutzung eines anderen Compilers mit beinahe exakt denselben Optionen und Parametern, sowie in der Nutzung nur dieses einen Features erschöpfen, und deswegen also offensichtlich keine größeren Änderungen am Projekt und am Code erfordern würde. Die Abneigungen und Vorurteile gegen C++ scheinen bei einigen Forenteilnehmern ziemlich tief zu sitzen. ;-)
Die Frage war doch, ob etwas auch in C geht, oder nur in C++.
Ein T. schrieb: > Was hindert Dich denn daran, C++ zu benutzen? Dieses. Nur mal ein altes Programm von gcc auf g++ geändert:
1 | cc1plus: warning: command line option '-std=c11' is valid for C/ObjC but not for C++ |
2 | cc1plus: warning: command line option '-Wnested-externs' is valid for C/ObjC but not for C++ |
3 | cc1plus: warning: command line option '-Wbad-function-cast' is valid for C/ObjC but not for C++ |
4 | ---- |
5 | In file included from imghdr-syslib.c:4: |
6 | ../include/imageheader.h:23:16: error: expected constructor, destructor, or type conversion before '(' token |
7 | 23 | _Static_assert (sizeof(image_struct) == 108, " Bad struct size"); |
8 | ---- |
9 | imghdr-syslib.c:12:4: warning: C++ designated initializers only available with -std=c++2a' or '-std=gnu++2a' |
10 | 12 | .top_of_stack = &tos, // 00 0 Initial SP (linker script) |
11 | | ^ |
12 | imghdr-syslib.c:13:4: warning: C++ designated initializers only available with -std=c++2a' or '-std=gnu++2a' |
13 | 13 | .crt0 = crt0, // 04 1 Initial PC "Reset-Handler |
Der erste Eindruck: da geht ja einiges nicht mehr... OK, die ersten Warnungen sind nur lästig. _Static_assert war ganz nett, aber egal. Aber designated initializers würden mir wirklich fehlen. Edit: es kommt noch "besser":
1 | imghdr-syslib.c:17:4: error: either all initializer clauses should be designated or none of them should be |
Und noch einen:
1 | typedef volatile struct iwdg_struct { |
2 | // 0x00 IWDG_KR IWDG Key register |
3 | uint32_t KR; // 16; // 0 Key value (write only, read 0000h) |
4 | // 0x04 IWDG_PR IWDG Prescaler register |
5 | uint32_t PR; // 3; // 0 PR[2:0] (Prescaler divider) |
6 | // (...) |
7 | } iwdg_struct; |
8 | ----------------- |
9 | ../include/STM/iwdg.h:60:3: error: conflicting declaration 'typedef volatile struct iwdg_struct iwdg_struct' |
10 | 60 | } iwdg_struct; |
11 | | ^~~~~~~~~~~ |
12 | ../include/STM/iwdg.h:41:25: note: previous declaration as 'struct iwdg_struct' |
13 | 41 | typedef volatile struct iwdg_struct { |
14 | | ^~~~~~~~~~~ |
nun ja, das ist für mich Grund genug. Ja, das kann man bestimmt alles reparieren. Vielleicht beim nächsten Programm.
:
Bearbeitet durch User
Bauform B. schrieb: > Dieses Sagt ja niemand, dass eine Migration ganz ohne Aufwand geht. C++ ist eben nicht vollständig rückwärtskompatibel zu C.
Bauform B. schrieb: > Dieses. Hm, okay, das sind gute Gründe, wenngleich ich glaube, daß sich die meisten davon mit einem aktuellen g++ und "-std=gnu++20" beheben lassen. HTH, YMMV. Ansonsten habe ich leider auch keine Idee, wie sich das mit C lösen läßt. Allerdings bin ich keine Referenz, ich benutze C schon lange nur noch in sehr, sehr wenigen Ausnahmefällen. ;-)
Bauform B. schrieb: > Der erste Eindruck: da geht ja einiges nicht mehr... OK, die ersten > Warnungen sind nur lästig. Da muss man eben die Warnungs-Einstellungen anpassen. Dass der C++-Code nicht gleichzeitig C99 sein kann, ist ja logisch. > _Static_assert war ganz nett, aber egal. Eigentlich sollte man das eh über das Makro static_assert() verwendet. Damit hätte es dann auch in C++ funktioniert. https://en.cppreference.com/w/c/error/static_assert https://en.cppreference.com/w/cpp/language/static_assert > Aber designated initializers würden mir wirklich fehlen. Die gibt es zwar ab C++20, haben aber den großen Nachteil, dass sie in der gleichen Reihenfolge genant sein müssen, in der auch die Members definiert sind. Das macht leider den größten Vorteil dieser Art der Initialisierung kaputt. > ../include/STM/iwdg.h:60:3: error: conflicting declaration 'typedef > volatile struct iwdg_struct iwdg_struct' > 60 | } iwdg_struct; > | ^~~~~~~~~~~ > ../include/STM/iwdg.h:41:25: note: previous declaration as 'struct > iwdg_struct' > 41 | typedef volatile struct iwdg_struct { > | ^~~~~~~~~~~ Hmm, das scheint nur bei volatile aufzutreten. Ich nehme an, dass sich das volatile nicht auf den Typedef überträgt und C++ es deshalb als anderen Typ mit gleichem Namen sieht. Generell braucht man in C++ an der Stelle aber das typedef gar nicht.
Bauform B. schrieb: > Der erste Eindruck: da geht ja einiges nicht mehr... OK, Ist es nicht irgendwie - äh - inkonsequent, vom Compiler zu verlangen, mehr Fehler zu finden, ohne mehr Fehler zu finden?
Rolf M. schrieb: >> Aber designated initializers würden mir wirklich fehlen. > > Die gibt es zwar ab C++20, haben aber den großen Nachteil, dass sie in > der gleichen Reihenfolge genant sein müssen, in der auch die Members > definiert sind. Das macht leider den größten Vorteil dieser Art der > Initialisierung kaputt. Echt jetzt? Ich kann es kaum glauben. Also auch in der allerneuesten Version :( Ist das so schwer zu implementieren? Das gibt's doch schon seit C11? Markus F. schrieb: > Ist es nicht irgendwie - äh - inkonsequent, vom Compiler zu verlangen, > mehr Fehler zu finden, ohne mehr Fehler zu finden? Naja, also so gesehen, nun ja... Mein Wunsch ist in Erfuellung gegangen, der g++ findet sogar viel mehr Fehler als der gcc, was will ich mehr :)
Bauform B. schrieb: > Wilhelm M. schrieb im >> In C++ benutze ich schon immer ein structure-mapping mit >> eingenen Register-Typen, so dass auch nur die richtigen >> Flags für die Register benutzt werden können, ansonsten >> Compile-Zeit-Fehler > Könnte man das in C ohne ++ auch haben? Etwas ähnliches erreicht man > wohl mit Bitfeldern in der struct, aber das ist umständlich, wenn man > mehrere Bits gleichzeitig setzen muss. Hi Bauform B, darf ich nochmal nachfragen: ich verstehe deine Frage nicht. Dein Code nutzt doch structure mapping? Zumnindest zeigst Du später C++ Fehlermeldungen einer HAL in C. Um was geht es Dir genau? Willst Du Warnings wenn Du versehentlich falsche Konstanten einem Register zuweist? A la
1 | GPIOA.MODE = IWDG_PRESCALER_128; // UPS |
Würde mich auch interessieren, wie Wilhelm M. das gelöst hat. Hast Du eigene Header in C++ dafür erstellt?
Klaus H. schrieb: > Zumnindest zeigst Du später C++ Fehlermeldungen Das war nur meine Antwort auf die Frage "warum benutzt du nicht C++". Ich hatte da nur kurz versucht, ein altes C-Programm mit g++ statt mit gcc zu übersetzen. > Hast Du eigene Header in C++ dafür erstellt? Nein, überhaupt nicht, ich habe außer diesem Versuch noch nichts mit C++ gemacht. Aber alle schwärmen davon und neugierig bin ich auch.
Bauform B. schrieb: > Ich hatte da nur kurz versucht, ein altes C-Programm mit g++ statt mit > gcc zu übersetzen. Die Frage zielte nicht auf C++. Der Beispiel-Code, den Du in Deinem Programm nutzt, ist ja C Sourcecode, der structure-mapping auf Register nutzt. Ging es Dir um die Frage wie man jetzt C structure-mappings zusätzlich mit weiteren Fehleranalysen absichert?
Wilhelm M. schrieb im > In C++ benutze ich schon immer ein structure-mapping mit > eingenen Register-Typen, so dass auch nur die richtigen > Flags für die Register benutzt werden können, ansonsten > Compile-Zeit-Fehler Würde mich auch interessieren, wie Du das gelöst hast. Hast Du eigene Header in C++ dafür erstellt?
Bauform B. schrieb: > Echt jetzt? Ich kann es kaum glauben. Also auch in der allerneuesten > Version :( Ist das so schwer zu implementieren? Das gibt's doch schon > seit C11? Das ist in C++ so notwendig, denn das ist nun mal die Art, wie die Datenelemente eines Objektes initialisiert werden - und das ist seit Urzeiten so (s.a. Initialisierungslisten von ctor'en). Von daher ist es konsequent, das auch hier so umzusetzen. Tja, einer der Unterschiede zwischen C und C++. C++ ist halt keine Obermenge von C.
Klaus H. schrieb: > Wilhelm M. schrieb im >> In C++ benutze ich schon immer ein structure-mapping mit >> eingenen Register-Typen, so dass auch nur die richtigen >> Flags für die Register benutzt werden können, ansonsten >> Compile-Zeit-Fehler > > Würde mich auch interessieren, wie Du das gelöst hast. > Hast Du eigene Header in C++ dafür erstellt? Dann solltest Du das auch in dem passenden Thread fragen und nicht hier, wo man das nur durch Zufall mitbekommt. In Kürze: In dem Aggregat-Typ einer internen Peripherie (z.B. Timer, ...) werden statt std::byte spezielle DT verwendet. Diese werden aus templates erzeugt, für z.B. DataRegister, ControlRegister, FlagRegister. Je nach Semantik der HW-Register. Parametriert werden diese templates mit den Typen der möglichen Werte dieses Registers (bei mir: Aufzählungstypen). Der aufwändigste Punkt ist also das Erzeugen der enum-Typen. Dies habe ich anfänglich zu Fuß gemacht. Hört sich nach viel Arbeit an, ging jedoch nach Bedarf (zusammen mit den Aggregaten, dem Adress-Mapping, ...) und damit überschaubar. Dann hatte ich mal ein ein Python-Script, was auch der XML-Beschreibung der Peripherie-Register das Zeug erzeugt hat. Das funktioniert aber leider nicht mehr, weil das XML-Schema sich geändert hat. Nun mache ich notwendige Ergänzungen wieder nach Bedarf ;-)
Bauform B. schrieb: > Rolf M. schrieb: >>> Aber designated initializers würden mir wirklich fehlen. >> >> Die gibt es zwar ab C++20, haben aber den großen Nachteil, dass sie in >> der gleichen Reihenfolge genant sein müssen, in der auch die Members >> definiert sind. Das macht leider den größten Vorteil dieser Art der >> Initialisierung kaputt. > > Echt jetzt? Ich kann es kaum glauben. Problem bei C++ ist, dass ein Initializer das Ergebnis eines Funktionsaufrufs sein darf, und so ein Funktionsaufruf kann Seiteneffekte haben. Intuitiv wüede man die Funktionsaufrufe "von links nach rechts" auswerten, und das Ergebnis wäre denn i.A. abhängig von der Reihenfolge. Eine Design-Entscheidung wäre, die Verantwortung komplett dem Anwender zu überlassen. Eine andere Design-Entscheidung wäre, etwas Ordnung in die Sache zu bringen und nur Initializer in ihrer natürlchen Reihenfpolge zuzulassen. Offenbar hat man den "sichereren" Weg No. 2 gewählt. ...und solche Problemchen hat man in C nicht, weil da ein Initializer nicht das Ergebnis eines Funktionsaufrufs sein darf, auch wenn das Ergebnis zu Compilezeit bekannt ist. Keine Ahnung wie das mit C23 + constexpr gelöst ist; vermutlich dadurch, dass constexpr-Funktionen keine Seiteneffekte haben dürfen, so dass deren Aufrufe kommutieren.
:
Bearbeitet durch User
Johann L. schrieb: > Problem bei C++ ist, dass ein Initializer das Ergebnis eines > Funktionsaufrufs sein darf, und so ein Funktionsaufruf kann > Seiteneffekte haben. > > Eine andere Design-Entscheidung wäre, etwas Ordnung in die Sache zu > bringen und nur Initializer in ihrer natürlchen Reihenfpolge zuzulassen. OK, wenigstens gibt es eine vernünftige Erklärung, danke dafür! Man kann eben nicht alles auf einmal haben...
Wilhelm M. schrieb: > Bauform B. schrieb: >> Echt jetzt? Ich kann es kaum glauben. Also auch in der allerneuesten >> Version :( Ist das so schwer zu implementieren? Das gibt's doch schon >> seit C11? > > Das ist in C++ so notwendig, denn das ist nun mal die Art, wie die > Datenelemente eines Objektes initialisiert werden - und das ist seit > Urzeiten so (s.a. Initialisierungslisten von ctor'en). Von daher ist es > konsequent, das auch hier so umzusetzen. Das stimmt aber nicht. Ich wünschte, es wäre so wie bei den Initialisierungslisten von Konstruktoren. Bei denen kann man die Member auch in einer anderen Reihenfolge angeben. Die Initialisierung erfolgt dann in der Reihenfolge der Definition der Member, nicht in der Reihenfolge in der Initialisierungsliste. Bei den designated initializers bricht der Compiler dagegen mit Fehler ab, wenn die Reihenfolge nicht übereinstimmt. Also ein grundlegend unterschiedliches Verhalten.
:
Bearbeitet durch User
Rolf M. schrieb: > Wilhelm M. schrieb: >> Bauform B. schrieb: >>> Echt jetzt? Ich kann es kaum glauben. Also auch in der allerneuesten >>> Version :( Ist das so schwer zu implementieren? Das gibt's doch schon >>> seit C11? >> >> Das ist in C++ so notwendig, denn das ist nun mal die Art, wie die >> Datenelemente eines Objektes initialisiert werden - und das ist seit >> Urzeiten so (s.a. Initialisierungslisten von ctor'en). Von daher ist es >> konsequent, das auch hier so umzusetzen. > > Das stimmt aber nicht. Was stimmt nicht? > Ich wünschte, es wäre so wie bei den > Initialisierungslisten von Konstruktoren. Bei denen kann man die Member > auch in einer anderen Reihenfolge angeben. Die Initialisierung erfolgt > dann in der Reihenfolge der Definition der Member, nicht in der > Reihenfolge in der Initialisierungsliste. Genau. Das sagte ich oben. > Bei den designated initializers bricht der Compiler dagegen mit Fehler > ab, wenn die Reihenfolge nicht übereinstimmt. Also ein grundlegend > unterschiedliches Verhalten. Nein. Die Datenelemente werden immer in derselben Reihenfolge initialisiert. In dem einen wie in dem anderen Fall.
Wilhelm M. schrieb: > Was stimmt nicht? Dass das Verhalten gleich wäre. >> Bei den designated initializers bricht der Compiler dagegen mit Fehler >> ab, wenn die Reihenfolge nicht übereinstimmt. Also ein grundlegend >> unterschiedliches Verhalten. > > Nein. > Die Datenelemente werden immer in derselben Reihenfolge initialisiert. > In dem einen wie in dem anderen Fall. Der Standard sagt unter "List-initialization": "The ordered identifiers in the designators of the designated-initializer-list shall form a subsequence of the ordered identifiers in the direct non-static data members of T." und bringt auch ein Beispiel:
1 | struct A { int x; int y; int z; }; |
2 | A a{.y = 2, .x = 1}; // error: designator order does not match declaration order |
3 | A b{.x = 1, .z = 2}; // OK, b.y initialized to 0 |
Rolf M. schrieb: > Wilhelm M. schrieb: >> Was stimmt nicht? > > Dass das Verhalten gleich wäre. Ich habe davon gesprochen, dass die Reihenfolge in beiden Fällen gleich ist. Ich habe nicht davon gesprochen, dass u.U. eine Warnung auftritt wogegen im anderen Fall ein Fehler. Also: die Reihenfolge der Initialisierung ist (und muss) immer gleich sein.
Wilhelm M. schrieb: > Rolf M. schrieb: >> Wilhelm M. schrieb: >>> Was stimmt nicht? >> >> Dass das Verhalten gleich wäre. > > Ich habe davon gesprochen, dass die Reihenfolge in beiden Fällen gleich > ist. Nö. Das hast du vielleicht gemeint, aber gesprochen hast du davon nirgends. Es ging um diese Aussage: Rolf M. schrieb: >> Aber designated initializers würden mir wirklich fehlen. > > Die gibt es zwar ab C++20, haben aber den großen Nachteil, dass sie in > der gleichen Reihenfolge genant sein müssen, in der auch die Members > definiert sind. und du meintest dazu: Wilhelm M. schrieb: > Das ist in C++ so notwendig, denn das ist nun mal die Art, wie die > Datenelemente eines Objektes initialisiert werden - und das ist seit > Urzeiten so (s.a. Initialisierungslisten von ctor'en). Von daher ist es > konsequent, das auch hier so umzusetzen. Aber genau diese Vorgabe (Reihenfolge bei den Initializers muss der bei der Definition entsprechen) ist bei den Konstruktor-Initialisierungslisten so nicht gegeben. Also ist es eben nicht konsequent, weil unterschiedlich umgesetzt. Und genau dieser Zwang zur gleichen Reihenfolge ist das, was mich an den designated-initializers in C++ wirklich stört.
:
Bearbeitet durch User
Rolf M. schrieb: > Wilhelm M. schrieb: >> Das ist in C++ so notwendig, denn das ist nun mal die Art, wie die >> Datenelemente eines Objektes initialisiert werden - und das ist seit >> Urzeiten so (s.a. Initialisierungslisten von ctor'en). Von daher ist es >> konsequent, das auch hier so umzusetzen. > > Aber genau diese Vorgabe (Reihenfolge bei den Initializers muss der bei > der Definition entsprechen) ist bei den > Konstruktor-Initialisierungslisten so nicht gegeben. Wenn Du genau liest, steht dort, wie die Objekte initialisiert werden! Und die ist nun mal immer gleich (egal wie die Initialisierungsliste geordnet ist). Den Verweis auf die Initlisten habe ich dort deswegen gezogen, weil auch dort die Reihenfolge eben auch der Deklarationsreihenfolge entspricht, egal wie die Initliste geordnet ist. Dort gibt es leider(!) nur eine Warnung.
Wilhelm M. schrieb: > Der aufwändigste Punkt ist also das Erzeugen der enum-Typen. Dies habe > ich anfänglich zu Fuß gemacht. Hört sich nach viel Arbeit an, ging > jedoch nach Bedarf (zusammen mit den Aggregaten, dem Adress-Mapping, > ...) und damit überschaubar. Dann hatte ich mal ein ein Python-Script, > was auch der XML-Beschreibung der Peripherie-Register das Zeug erzeugt > hat. Das funktioniert aber leider nicht mehr, weil das XML-Schema sich > geändert hat. Nun mache ich notwendige Ergänzungen wieder nach Bedarf > ;-) Läßt sich das Python-Skript nicht an das neue XML-Schema anpassen?
Wilhelm M. schrieb: > Klaus H. schrieb: >> Würde mich auch interessieren, wie Du das gelöst hast. >> Hast Du eigene Header in C++ dafür erstellt? > Dann solltest Du das auch in dem passenden Thread fragen und nicht hier, > wo man das nur durch Zufall mitbekommt. Sorry, du hattest in diesem Thread schon teilgenommen und im anderen Thread ging es ja eher um ein Compiler Problem. Kannst Du mal ein Beispiel zeigen? Ich hatte schon verschieden Varianten mit templates und structs überlegt. Aber keine davon war so, dass ich das Gefühl hatte: ja, die erhöhte Fehleraufdeckung rechtfertigt den Aufwand.
:
Bearbeitet durch User
Bauform B. schrieb: > Aber > designated initializers würden mir wirklich fehlen. Ich wüßte nicht, wie ich ohne die klarkommen sollte. Sich nur auf die Reihenfolge verlassen zu müssen, erscheint mir extrem fehlerträchtig. Ich habe oft Arrays von Structs, die sehr groß werden, da kann ich mir nicht alles merken. Und bei Änderungen würde ja alles durcheinander gewürfelt. Hier mal ein Auszug:
1 | .par.dac[DAC_VENERGY].gain = DAC_6KV_GAIN, |
2 | .par.dac[DAC_VENERGY].offset = DAC_6KV_OFFSET, |
3 | .par.dac[DAC_VENERGY].lower = 0.0, |
4 | .par.dac[DAC_VENERGY].upper = MOD_6KV_LIMIT, |
5 | .par.dac[DAC_VENERGY].val = 0.0 * MOD_6KV_SGAIN, |
6 | .par.adc[ADC_VENERGY].gain = MON_6KV_GAIN, |
7 | .par.adc[ADC_VENERGY].offset = MON_6KV_OFFSET, |
8 | .par.adc[ADC_IENERGY].gain = MONI_6KV_GAIN, |
9 | .par.adc[ADC_IENERGY].offset = MONI_6KV_OFFSET, |
10 | .par.adc[ADC_IENERGY].comp = MONI_6KV_COMP, |
Man sieht hier, daß die Parameter je Modul gruppiert sind, die sich aber in Structs an 3 verschiedenen Adressen befinden. Ein Zwang zu aufsteigenden Adressen würde alles vollkommen unleserlich machen.
:
Bearbeitet durch User
OK, das geht in C++ so nicht, aber ich finde die Darstellung nicht gut. Darin sehe ich keinen Vorteil. Es geht die Hierarchie der Daten verloren. Eine verschaltelte Initialisierung finde ich besser. So müsste es in C und in C++20 funktionieren.
1 | data_t data = { |
2 | .par = { |
3 | .dac = { |
4 | { /*DAC_VENERGY*/ |
5 | .gain = DAC_6KV_GAIN, |
6 | .offset = DAC_6KV_OFFSET, |
7 | .lower = 0.0, |
8 | .upper = MOD_6KV_LIMIT, |
9 | .val = 0.0 * MOD_6KV_SGAIN |
10 | }
|
11 | },
|
12 | .adc = { |
13 | { /* ADC_VENERGY */ |
14 | .gain = MON_6KV_GAIN, |
15 | .offset = MON_6KV_OFFSET |
16 | },
|
17 | { /* ADC_IENERGY*/ |
18 | .gain = MONI_6KV_GAIN, |
19 | .offset = MONI_6KV_OFFSET, |
20 | .comp = MONI_6KV_COMP |
21 | }
|
22 | }
|
23 | }
|
24 | };
|
Ein Nachteil in C++ ist IMHO das Array designators nicht funktionieren. Aber das ist für micht verschmerzbar.
Peter D. schrieb: > Ich habe oft Arrays von Structs, die sehr groß werden, da kann ich mir > nicht alles merken. Und bei Änderungen würde ja alles durcheinander > gewürfelt. Was sollte da durcheinander gewürfelt werden?
Wilhelm M. schrieb: > Was sollte da durcheinander gewürfelt werden? Ich meinte, wenn man keine designated initializers verwenden könnte. Ich hab das hier im Forum kennen und schätzen gelernt und benutze es seitdem ausschließlich. Die Initialisierung nach Reihenfolge hatte mich schon immer geärgert und oft Fehler verursacht. Während einer Projektentwicklung kommt es regelmäßig vor, daß Elemente verschoben, hinzugefügt, umbenannt oder gelöscht werden. Ich kenne keinen, wo schon zu Anfang gleich alles in Stein gemeißelt ist. Dagegen spricht schon, daß die Anwender nach der ersten Version noch haufenweise Extrawünsche haben, die man nachträglich implementieren muß. Ich arbeite daher auch gerne mit enums, die die Order in einem Array festlegen. Ich überlasse also nichts dem Zufall. Perfekt wäre es noch, wenn man auch bei einem Funktionsaufruf die Argumente namentlich übergeben könnte, d.h. nicht zwingend nach Reihenfolge. Da oft 3-4 Argumente ausreichen, kann ich mir das grad noch merken.
:
Bearbeitet durch User
Beitrag #7374072 wurde vom Autor gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.