Hi was nimmt idealerweise von einem type für den index einer for loop #define MAX_NUM 32 for (uint32_t index = 0; index< MAX_NUM; index++) soll ich für index int, uint32_t, uint16_t oder uint8_t nehmen? Was ist der bessere Programmier Stil? Was generioert den effizienteren code? Ich hatte mal gehört dass wenn ich uint8_t oder nicht den native Register width nehme dass ein "and" noch dazu kommt!
:
Bearbeitet durch User
H. R. schrieb: > soll ich für index int, uint32_t, uint16_t oder uint8_t nehmen? > Was ist der bessere Programmier Stil? Was generioert den effizienteren > code? Kommt schwerstens auf den Zielprozessor an. Der size_t wäre für moderne 32-Bitter schnell, für den AVR 8-Bitter langsam. Es gäbe notfalls auch noch sowas wie uint_fast8_t, wenn der Schleifenindex garantiert <= 255 ist. Der einfache int oder unsigned int ist nur auf den 8-Bittern langsam, weil int mindestens 2 Byte breit sein muss.
Eigentlich ist int genau dafür vorgesehenen: eine Ganzzahl in der Default-Prozessor-Breite.
A. S. schrieb: > Eigentlich ist int genau dafür vorgesehenen: eine Ganzzahl in der > Default-Prozessor-Breite. Nö. Er muss ja mindestens 16 Bit haben. Also für alles mit weniger als 16 Bit ziemlich für'n Arsch. Naja, nicht ganz, manche Compiler erkennen in manchen Situationen immerhin die völlig unnütze Aufgeblasenheit und reduzieren sie kommentarlos auf das tatsächlich Nötige...
Das Problem bei diesem Code ist, dass der max. Indexwert durch den Präprozessor editiert wird, und damit keine Beziehung zum DT der Schleifenvariable index hat. Deswegen habe ich oben size_t gesagt. Denn size_t ist immer ausreichend groß. Doch kleiner kann man den DT hier nicht machen, weil ein uint8_t schnell zu klein sein kann, falls man später mal das define ändert. Der Code bricht also leicht. Auch wenn an dieser speziellen Stelle wohl die meisten Compiler warnen werden. Jedoch an anderen Stellen? Deswegen wäre es besser, mit einer Meta-Funktion denn minimalen DT aus der Konstanten zu berechnen:
1 | constexpr auto MAX{32}; |
2 | //...
|
3 | using index_t = type_for_t<MAX>; |
4 | for(index_t i{}; i < MAX; ++i) {...} |
H. R. schrieb: > Ich hatte mal gehört dass wenn ich uint8_t oder nicht den native > Register width nehme dass ein "and" noch dazu kommt! Ja so ähnlich. Immer wenn dein Int nicht der nominalen Datenbreite (Bits) entspricht, mit dem dein µC arbeitet, muss "rumgewurschtelt" werden.
Ob besser signed oder unsigned, hängt dann noch davon ab, was mit dem Zähler in der Schleife gemacht wird. Oliver
H. R. schrieb: > Hi > was nimmt idealerweise von einem type für den index einer for loop Ich nehme int, wenn's keinen konkreten Grund gibt, was anderes zu nehmen. > Was ist der bessere Programmier Stil? Was generioert den effizienteren > code? > Ich hatte mal gehört dass wenn ich uint8_t oder nicht den native > Register width nehme dass ein "and" noch dazu kommt! Das ist vom Prozessor abhängig. Bei manchen ist eine bestimmte Größe besonders effizient, bei anderen macht es kaum Unterschied. Die native Größe ist natürlich in der Regel am schnellsten. Wilhelm M. schrieb: > Das Problem bei diesem Code ist, dass der max. Indexwert durch den > Präprozessor editiert wird, und damit keine Beziehung zum DT der > Schleifenvariable index hat. Ich sehe darin kein Problem, da es sich um eine Compilezeit-Konstante handelt. Offiziell werden Vergleiche (und alle anderen arithmetischen Operationen) sowieso grundsätzlich immer mit int-Breite durchgeführt. Der Compiler darf das allerdings optimieren, wenn er garantieren kann, dass sich das Ergebnis dadurch nicht ändert. Damit ist es so oder so für die Effizienz der Schleife egal, ob der Vergleichswert jetzt ein int oder was kleineres ist ist. > Deswegen habe ich oben size_t gesagt. Denn size_t ist immer ausreichend > groß. Doch kleiner kann man den DT hier nicht machen, weil ein uint8_t > schnell zu klein sein kann, falls man später mal das define ändert. Das kommt ganz darauf an, was man machen will. Letztendlich könnte man die gleiche Aussage über size_t treffen. Im einfachsten Fall schreibt man beim #define einen Kommentar hin, der angibt, dass der Wert nicht größer als 255 sein darf und fügt eine eine compile-time-Assertion ein. Den Typ prophylaktisch einfach unnötig groß zu machen, nur weil man ja später irgendwann theoretisch vielleicht mal mehr brauchen könnte, halte ich jedenfalls für eine wenig geeignete Strategie. > Deswegen wäre es besser, mit einer Meta-Funktion denn minimalen DT aus > der Konstanten zu berechnen: > constexpr auto MAX{32}; > //... > using index_t = type_for_t<MAX>; > for(index_t i{}; i < MAX; ++i) {...} Das geht dann allerdings nur in C++. Oliver S. schrieb: > Ob besser signed oder unsigned, hängt dann noch davon ab, was mit dem > Zähler in der Schleife gemacht wird. Ja. Man sollte vor allem auch vermeiden, signed und unsigned zu mischen.
Rolf M. schrieb: > Der Compiler darf das allerdings optimieren, wenn er garantieren kann, > dass sich das Ergebnis dadurch nicht ändert. Und das tut er mit Sicherheit, wenn der DT von index so klein wie möglich ist (hier: uint8_t). Kann er das nicht nachweisen, optimiert er es nicht. ich habe ja auch oben geschrieben, dass das für diese eine Schleife kein Problem für den Compiler ist. Allerdings kann das natürlich noch weiter gehen ... Rolf M. schrieb: > Letztendlich könnte man > die gleiche Aussage über size_t treffen. Nein. size_t ist immer (!) ausreichend groß für die jeweilige Plattform, um als Indizierungstyp auszureichen. Rolf M. schrieb: > Im einfachsten Fall schreibt > man beim #define einen Kommentar hin, der angibt, dass der Wert nicht > größer als 255 sein darf und fügt eine eine compile-time-Assertion ein. Und falls es dann doch mal größer ist, und die Assertion fehl schlägt, darf man anschließend überall im Code ändern. Prima ;-) Rolf M. schrieb: > Das geht dann allerdings nur in C++. Es war keine Sprache erwähnt. Der Code kann genauso gut C++ sein.
Wilhelm M. schrieb: > Rolf M. schrieb: >> Letztendlich könnte man >> die gleiche Aussage über size_t treffen. > > Nein. size_t ist immer (!) ausreichend groß für die jeweilige Plattform, > um als Indizierungstyp auszureichen. ... für Array-Indizes. Wir wissen aber nicht, wofür diese Schleife verwendet wird. > Rolf M. schrieb: >> Im einfachsten Fall schreibt >> man beim #define einen Kommentar hin, der angibt, dass der Wert nicht >> größer als 255 sein darf und fügt eine eine compile-time-Assertion ein. > > Und falls es dann doch mal größer ist, und die Assertion fehl schlägt, > darf man anschließend überall im Code ändern. Prima ;-) Wieso "überall"? Man muss es genau an dieser Stelle ändern: H. R. schrieb:
1 | for (uint32_t index = 0; index< MAX_NUM; index++) |
2 | ^^^^^^^^
|
> Rolf M. schrieb: >> Das geht dann allerdings nur in C++. > > Es war keine Sprache erwähnt. Ja, eben. Du hast aber C++ angenommen. Ich hab lediglich darauf hingewiesen, dass es nur dort funktioniert. > Der Code kann genauso gut C++ sein. Oder halt C.
Rolf M. schrieb: > ... für Array-Indizes. Wir wissen aber nicht, wofür diese Schleife > verwendet wird. Genau, das ist das Problem! Rolf M. schrieb: > Wieso "überall"? Man muss es genau an dieser Stelle ändern: Nein, überall wo der Textersatz MAX_NUM verwendet wird. Und da der noch nicht einmal gescoped ist, kann das überall sein.
H. R. schrieb: > Was generioert den effizienteren code? Wenn in der Schleife ein Haufen Rechnerei ist, ist das Nachdenken darüber Zeitverschwendung. Ansonsten ein fast_intX_t und ein geeignetes assert oder Makro das sicherstellt dass der Bereich groß genug ist.
1 | #include <stdint.h> |
2 | |
3 | #define MAX_NUM (32)
|
4 | |
5 | #if (MAX_NUM) < 256
|
6 | typedef uint_fast8_t perfect_loop_t; |
7 | #elif (MAX_NUM) < 65536
|
8 | typedef uint_fast16_t perfect_loop_t; |
9 | #elif (MAX_NUM) < 4294967296
|
10 | typedef uint_fast32_t perfect_loop_t; |
11 | #else
|
12 | #error "Haben Sie es nicht ein Bischen kleiner ?"
|
13 | #endif
|
14 | |
15 | for (perfect_loop_t index = (perfect_loop_t)0; index< (perfect_loop_t)(MAX_NUM); index++) |
So etwa ?
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.