Guten Morgen zusammen,
ich gehe gerade alte, nicht mehr ganz frisch riechende Code-Teile durch
und stelle fest, dass ich nie ein stringentes Namensschema entwickelt
habe. Ich habe das mal am Beispiel von clamp() durchexerziert, weil das
eine Funktion ist, die ich für jeden benutzten Datentyp mal
implementiert habe.
Die Funktion selbst ist nahezu banal:
1 | static inline int_fast8_t clamp(type *a, type llim, type ulim)
|
2 | {
|
3 | assert( llim <= ulim );
|
4 |
|
5 | if( *a > ulim )
|
6 | {
|
7 | *a = ulim;
|
8 | return 1;
|
9 | }
|
10 | else if( *a < llim )
|
11 | {
|
12 | *a = llim;
|
13 | return -1;
|
14 | }
|
15 | else
|
16 | {
|
17 | return 0;
|
18 | }
|
19 | }
|
Von der Namens-Logik aus <math.h> hießen die konkreten Funktionen:
1 | int_fast8_t fclamp(double *a, double llim, double ulim);
|
2 | int_fast8_t fclampf(float *a, float llim, float ulim);
|
3 | int_fast8_t flampfl(long double *a, long double llim, long double ulim);
|
(clamp() wäre nach dieser Logik identisch mit fclamp())
Von der Namens-Logik aus
https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html würde
für Integer-Datentypen gelten:
1 | int_fast8_t sclamp(int *a, int llim, int ulim);
|
2 | int_fast8_t sclampl(long int *a, long int llim, long int ulim);
|
3 | int_fast8_t sclampll(long long int *a, long long int llim, long long int ulim);
|
4 |
|
5 | int_fast8_t uclamp(unsigned int *a, unsigned int llim, unsigned int ulim);
|
6 | int_fast8_t uclampl(long unsigned int *a, long unsigned int llim, long unsigned int ulim);
|
7 | int_fast8_t uclampll(long long unsigned int *a, long long unsigned int llim, long long unsigned int ulim);
|
Wie sieht es mit den Datentypen aus <stdint.h> aus? Naiv würde ich
schreiben:
1 | int_fast8_t sclamp32(int32_t *a, int32_t llim, int32_t ulim);
|
2 | int_fast8_t uclamp16(uint16_t *a, uint16_t llim, uint16_t ulim);
|
a) Ist das Schema sinnvoll, oder gibt es etwas besseres?
b) Zur konkreten Funktion clamp() (da C keine Templates kennt): Gibt es
eine "schöne" Variante der Implementierung?
b1): Was sicherlich funktioniert ist eine Makro-Hölle aus ternären
Operatoren.
b2): Tatsächlich implementiert habe ich sclampll() und uclampll(),
alle anderen Integer-Funktionen rufen diese lediglich auf. Da alle
Funktionen static inline sind, hoffe ich, daß der Compiler selbst
erkennt, daß er den Integer nicht aufbohren muß. (Bei allen überprüften
Listings wurde diese Hoffnung auch nicht enttäuscht, aber das ist ja
keine allgemeine Bestätigung.)