Forum: Compiler & IDEs Namensschema für Funktionen


von Walter T. (nicolas)


Lesenswert?

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.)

: Verschoben durch User
von Walter T. (nicolas)


Lesenswert?

Nachtrag: So schlimm sieht die Makro-Lösung doch nicht aus:
1
    /* Generische Makro-Funktion fuer Clamp. Nicht fuer den direkten Aufruf gedacht
2
     * ist lo > hi, ist das Ergebnis unerwartet. */
3
    #define CLAMP(x, lo, hi) \
4
        (x) > (hi) ? (x)=(hi), 1 : \
5
        (x) < (lo) ? (x)=(lo), -1 : \
6
        0\
7
8
9
10
    static_inline int sclamp32(int32_t *x, int32_t lo, int32_t hi)
11
    {
12
        return CLAMP(*x, lo, hi);
13
    }

Die andere Frage bleibt natürlich.

von Walter T. (nicolas)


Lesenswert?

Ist der Wunsch nach ein wenig Ordnung im Quelltext so banal oder so 
abwegig?

von Tom (Gast)


Lesenswert?

Als Freund der Autovervollständigung würde ich die Funktionen nur im 
Suffix unterscheiden(clamp_u8, clamp_i32 etc.). Für meinen Geschmack ist 
das weniger hässlich; warum man die Datentypkennzeichnung auf Pre- und 
Suffix des Funktionsnamens verteilen sollte, erschließt sich mir nicht.

von Kolja L. (kolja82)


Lesenswert?

Tom schrieb:
> würde ich die Funktionen nur im
> Suffix unterscheiden(clamp_u8, clamp_i32 etc.). Für meinen Geschmack ist
> das weniger hässlich;

So gehe ich bei der Benennung von Messstellen vor.
Im coden habe ich zu wenig Erfahrung.

Jeder Name, den ich vergebe, sollte selbsterklärend sein.
Klappt aber nur, wenn das Projekt auch wirklich fertiggestellt wird...

von Wilhelm M. (wimalopaan)


Lesenswert?

Ich habe sehr wohl gelesen, dass es hierbei um C geht. Trotzdem gebe ich 
zu bedenken: warum nicht einfach Deinen Code mit einem C++ Compiler 
übersetzen und in diesem Fall einfach die Möglichkeit nutzen, Funktion 
zu überladen? Du kannst zwar templates benutzen, aber wenn Dir das zu 
"kompliziert" erscheint, reicht auch schlichtes Überladen.

Natürlich gibt es wie

- Inkompatibilitäten (Klassiker: unions)
- C-Erweiterungen (fixed-point, _flash)

Derartiges kannst Du weiterhin in C TUs belassen.
Wenn Du eh am Refaktorieren bist, kannst Du das ja mal checken ...

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
Noch kein Account? Hier anmelden.