präprozessr anweisung vs typedef vs const



  • ;fricky schrieb:

    dass 'const' #define vorzuziehen ist, wird in C++-kreisen gepredigt. naja, alles was aus der ecke kommt, ist sowieso mit vorsicht zu geniessen.

    ja bei kleinen dingen fängts an:)
    nicht das hier ein c vs. c++ off-topic thread entsteht 🤡



  • µngbd schrieb:

    Bashar schrieb:

    Diese ganzen #defines aus math.h, M_PI usw., sind leider nicht im Standard.

    Oje, das stimmt. Ich hab mich schon wieder mal auf die manpages verlassen. Man muss sich das abgewöhnen.
    🙂

    Wieso? Wenn's im Header nicht drinsteht, merkste das, wenn der Präppi oder Compiler meckert. Dann schreibst Du's einfach in math.h mit rein, fertig.



  • Bashar schrieb:

    supertux schrieb:

    Ich hab ehrlich gesagt noch nie ausprobiert und hab gar nicht dran gedacht, als ich den Beitrag schrieb. 🙄

    Wieso schreibst du dann, dass du das selbst so machst? Du simulierst dadurch eine fundierte Aussage.

    oje oje, jetzt habe ich ein bisschen Verwirrung gestiftet. Ich verwende sehr wohl enums anstatt #define, aber meine Werte sind stets hexazahlen, also sowas in der Art

    enum was_auch_immer {
      CAN_SDO_ERR_REG    = 0x1001,
      CAN_SDO_COBID_SYNC = 0x1005,
      CAN_SDO_SAVE_PARM  = 0x1010,
      ...
    }
    

    aber ich hab noch nie sowas mit floats gemacht, deshalb habe ich gar nicht dran gedacht, als ich den Beitrag schrieb. So habe ich das gemeint.



  • das leben könnt so einfach sein 😉

    #define CAN_SDO_ERR_REG 0x1001
    #define CAN_SDO_COBID_SYNC 0x1005
    #define CAN_SDO_SAVE_PARM 0x1010
    


  • Das was_auch_immer kann man auch weglassen wenns einen nicht interessiert. Aber für sowas ist enum echt nicht geeignet, enum ist nur richtig sinnvoll wenn einen die Werte nicht interessieren.
    Ich würde es aber trotzdem so machen:

    const int CAN_SDO_ERR_REG 0x1001;
    const int CAN_SDO_COBID_SYNC 0x1005;
    const int CAN_SDO_SAVE_PARM 0x1010;
    

    Mich irritiert das wenn der Compiler Code bemeckert und ich in meinen Code kucke und da steht was ganz anderes.

    Der Vorteil mit const int ist, dass sowas hier einen Fehler ergibt:

    struct bla *b;
    ...
    b = CAN_SDO_SAVE_PARM; //eigentlich war b.zustand = CAN_SDO_SAVE_PARM; gemeint
    

    Bei #define sucht man eine Weile.



  • ich finde enums angenhemer, weil ich sie sehr oft in switch Anweisungen verarbeite. Wenn ich was vergesse, teilt mir der Compiler das mit. Das passiert aber nicht mit defines.

    Außerdem lasse ich manchmal den Code nur durch den präpi durchlaufen und da ist es toll, wenn ich immer noch CAN_SDO_COBID_SYNC lese anstatt 0x1005, denn CAN_SDO_COBID_SYNC sagt mir mehr als 0x1005.

    Außerdem kann ich bei Funktionen an den Paramtern festhalten, welche Werte überhaupt möglich sind

    int object_do_something(enum was_auch_immer wai, ....);
    

    klar kann der Benutzer meiner Bibliotheken andere Werte reinschreiben, aber ohne groß dokumentieren zu müssen, wird jeder merken, dass nur die Werte des enums erlaubt sind. Mit

    int object_do_something(int wai, ....);
    

    ginge es nicht.



  • nwp2 schrieb:

    Bei #define sucht man eine Weile.

    dann stell dir für macros eine andere farbe ein z.b. rot oder so??

    const int CAN_SDO_ERR_REG 0x1001;
    const int CAN_SDO_COBID_SYNC 0x1005;
    const int CAN_SDO_SAVE_PARM 0x1010;
    

    wenn das so cool wär würden die konstanten in math.h z.b. M_PI doch

    const int M_PI xyz;// definiert sein sind sie aber nicht sondern
    #define M_PI xyz
    

    supertux schrieb:

    int object_do_something(enum was_auch_immer wai, ....);
    

    ja also damit hast du mich für enums begeistert 🙂



  • noobLolo schrieb:

    supertux schrieb:

    int object_do_something(enum was_auch_immer wai, ....);
    

    ja also damit hast du mich für enums begeistert

    beim debuggen sind sie auch gut, z.b. zeigt der debugger dir den symbolischen namen an. bei #defines siehst du nur den nackten zahlenwert.
    🙂



  • supertux schrieb:

    ich finde enums angenhemer, weil ich sie sehr oft in switch Anweisungen verarbeite. Wenn ich was vergesse, teilt mir der Compiler das mit. Das passiert aber nicht mit defines.

    Wie meinst Du das genau? Welches Vergessen befördert der Compiler zutage?

    SFRs deswegen als enums? Brauch' ich bei meinen Debuggern auch nicht, auf Source Level sehe ich den Quelltext (also die C-LOC), da ist noch nichts ersetzt und in ASM kann ich auch mal echt suchen, wenn ich soweit runter muß.

    Ich seh' jetzt einfach nur keinen tieferen Sinn, wenn' man's mir nochmal langsam erklärt, bitte?



  • pointercrash() schrieb:

    supertux schrieb:

    ich finde enums angenhemer, weil ich sie sehr oft in switch Anweisungen verarbeite. Wenn ich was vergesse, teilt mir der Compiler das mit. Das passiert aber nicht mit defines.

    Wie meinst Du das genau? Welches Vergessen befördert der Compiler zutage?

    bsp:

    enum wasauchimmer {
      A,
      B,
      C,
      ...
      X,
      Y,
      Z
    };
    
    void foo(enum wasauchimmer bar)
    {
      switch(bar)
      {
         case A:
         case B:
            mach was;
         ...
      }
    }
    

    angenommen ich habe den Fall für 'K' vergessen (absichtlich :default weggelassen), dann sagt mir der Compiler, dass der Fall 'K' nicht behandelt wird. Beim Compilieren merke ich den Fehler. Das mache ich solange bis der Compiler mir entweder keine Warnung mehr spuckt oder mir nur von den jenigen warnt, die unter 'default:' fallen würden. Erst dann schreib ich 'default:'.

    Außerdem werden bei enums mir die Konstanten semantisch zusammengefasst, das die Verwendung der Bibliothek erleichtert. Auch Doxygen zeigt automatisch die zusammengefasste Doku an einer Stelle. Wenn ich nur #defines hätte, wäre das nicht möglich.



  • pointercrash() schrieb:

    Brauch' ich bei meinen Debuggern auch nicht, auf Source Level sehe ich den Quelltext (also die C-LOC), da ist noch nichts ersetzt...

    nimm mal das:

    // in einer h datei
    typedef enum time_machine
    {
      gestern,
      heute,
      morgen,
    } time_machine_t;
    
    ------------- snip -------------
    
    // hier willst du debuggen
    void f (time_machine_t b)
    {  // <-- breakpoint
       ...
    }
    
    ------------- snip -------------
    
    // andere c-datei von 1000 dateien
    ...
    f (morgen);
    ...
    

    ^^ wenn du das debuggst, zeigt dir der debugger das 'b' als 'morgen' an. wären es defines, würdest du bloss eine 2 sehen.
    🙂


Anmelden zum Antworten