Makro funktioniert nicht, warum?



  • jizzer schrieb:

    Sonst noch vorschläge ?

    Für beliebige Exponenten sind mir keine problemlosen bekannt. Aber wenn du uns sagst, wofür du das brauchst, können wir vielleicht eines konstruieren, das zumindest die Probleme vermeidet, die du nicht haben willst.
    🙂

    Editgrammatik



  • Natürlich machen die Probleme mit Scopes. Der häufigste Zusammenhang ist in C++ mit numeric_limits, etwa

    #include <limits>
    #include <windows.h>
    
    // ...
    
    double d = std::numeric_limits<double>::max(); // KAWUMM!
    

    aber in reinem C kann einem sowas beispielsweise mit Funktionszeigern leicht auseinanderfliegen. Nimm an, ich modelliere ein Objektsystem in C und habe darin etwa folgendes:

    struct collection {
      void *max(collection *self, int (*compare)(void*, void*));
    };
    
    int compare_int(void *p, void *q) {
      return *(int*)p < *(int*)q;
    }
    
    /* ... */
    
    collection c;
    /* Fülle collection */
    
    int x = *(int*)c.max(&c, int_compare);
    

    Da definiere mal so ein max vor und sag mir, ob du die Fehlermeldungen noch verstehst.

    Was diesen Use-Case angeht, es macht keinen Sinn, das mit Makros zu versuchen. Es mag in manchen Compilern Erweiterungen geben, die so etwas ermöglichen, aber da sich das ganze mit einer Funktion lösen lässt, besteht wirklich keinerlei Grund, auf Makros zurückzugreifen - mit einer Funktion hast du all diese Probleme nicht, und du kannst Dinge damit machen, die mit einem Makro nicht gehen (es gibt beispielsweise keine Zeiger auf Makros).



  • Dann halt nich. dann muss ich mich wohl mit bestimmten fällen wie x² oder x³ zufrieden geben. wobei.. könnte man bspw.folgendes

    #define pow(x) (x) * (x)
    .
    .
    .
    pow(pow(x));

    tun, also Makros verschachteln?



  • abc.w schrieb:

    Ganz kurz: Makros sind Scheisse!

    Nein, das sind sie auch nicht. Manchmal ersapren Makros verdammt viel getippe:

    Z.b. in einer Bibliothek habe ich (Makros und Inhalt weitgehend geändert)

    #define get_value_typed(type, type_short_name, c_type)\
    int get_obj_ ##type_short_name(data_obj *cv, c_type *val)\
    {\
        int ret;\
        if(cv == NULL || val == NULL)\
            return 0;\
       if ((cv->dtype != TYPE_INVALID) && (cv->dtype != type))
            return 0;\
        ret = obj_request(cv, cv->read_to);\
        if(ret == 0)\
            return 0;\
        *val = (c_type) obj_get_value(cv);\
        return 1;
    }
    
    get_value_typed(TYPE_I8, i8,  int8_t);
    get_value_typed(TYPE_U8, u8, uint8_t);
    get_value_typed(TYPE_I16, i16,  int16_t);
    get_value_typed(TYPE_U16, u16, uint16_t);
    get_value_typed(TYPE_I32, i32,  int32_t);
    get_value_typed(TYPE_U32, u32, uint32_t);
    

    Damit hab ich sofort die Implementierung für Funktionen:

    int get_obj_i8(data_obj *cv, int8_t);
    int get_obj_u8(data_obj *cv, uint8_t);
    ....
    

    mngbd schrieb:

    supertux schrieb:

    Makros haben den großen Nachteil, dass sie nicht Typsicher sind und undefiniertes Verhalten hervorrufen können, was sehr schwer zu debuggen ist.

    Hmm, Funktionen können nichts Undefiniertes "hervorrufen"?
    🙂

    ja, das stimmt. Was ich aber sagen wollte, dass man mit Makros viel leichter nicht offensichtliche Fehler machen kann.



  • Der Typ hier verwendet pow als Makro. Aber wenn ich das ausführen will gehts nicht.

    http://c-buch.sommergut.de/Kapitel12/Symbolische-Konstanten-und-Makros.shtml



  • Er erläutert im umgebenden Text aber auch, warum das keine gute Idee ist.



  • Ich hab's jetzt nicht alles gelesen, aber warum kann es den keine Funktion sein?



  • Kann auch ne Funktion sein. Die Frage war eher interessehalber. In dem Link (s.o.) steht, trotz der Hinweise, warum das eine Fehlerquelle sein kann, dass man es so als Makro benutzen kann - genau das funktioniert aber nicht (bei ms visual studio 2008 zumindest), also hat er unrecht ?



  • jizzer schrieb:

    Kann auch ne Funktion sein. Die Frage war eher interessehalber. In dem Link (s.o.) steht, trotz der Hinweise, warum das eine Fehlerquelle sein kann, dass man es so als Makro benutzen kann - genau das funktioniert aber nicht (bei ms visual studio 2008 zumindest), also hat er unrecht ?

    Bei mir funktioniert sein Beispiel. Also machst du falsch, da du aber nicht sagt, was passiert, kann dir eh keiner helfen :p



  • #include <stdio.h>
    
    #define pow(a, b) (double atemp = a; for(;b>0;b--)a*=atemp;)
    
    void main()
    {
    
    	double base = 2;
    	int exp = 3;
    	printf("Ergebnis: %3f", pow(base, exp));
    }
    

    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2146: syntax error : missing ')' before identifier 'atemp'
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2065: 'atemp' : undeclared identifier
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2106: '=' : left operand must be l-value
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2143: syntax error : missing ')' before ';'
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2065: 'atemp' : undeclared identifier
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2059: syntax error : ')'
    1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2059: syntax error : ')'



  • Makro haben keine Return-Wert.



  • Ich verstehe nicht. Was genau ist der Fehler?



  • #include <stdio.h>
    
    void main()
    {
        double base = 2;
        int exp = 3;
        printf("Ergebnis: %3f", (double atemp = base; for(;exp>0;exp--)base*=atemp;));
    }
    

    Ich kann kein C - sag mir was an dieses C Programm nicht stimmt.

    Error 1 error C2146: syntax error : missing ')' before identifier
    Error 2 error C2065: 'atemp' : undeclared identifier
    Error 3 error C2106: '=' : left operand must be l-value
    Error 4 error C2143: syntax error : missing ')' before ';'
    Error 5 error C2065: 'atemp' : undeclared identifier
    Error 6 error C2059: syntax error : ')'
    Error 7 error C2059: syntax error : ')'



  • supertux schrieb:

    abc.w schrieb:

    Ganz kurz: Makros sind Scheisse!

    Nein, das sind sie auch nicht. Manchmal ersapren Makros verdammt viel getippe: ...

    ...
    

    Damit hab ich sofort ...

    ....
    

    Ja, kann sein, habe versucht, deinen Code zu verstehen und habe cpp drüberlaufen lassen (musste in deinem Code noch hie und da ein ** einfügen) und bekomme folgendes:

    int get_obj_i8(data_obj *cv, int8_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_I8)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (int8_t) obj_get_value(cv); return 1;};
    int get_obj_u8(data_obj *cv, uint8_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_U8)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (uint8_t) obj_get_value(cv); return 1;};
    int get_obj_i16(data_obj *cv, int16_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_I16)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (int16_t) obj_get_value(cv); return 1;};
    int get_obj_u16(data_obj *cv, uint16_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_U16)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (uint16_t) obj_get_value(cv); return 1;};
    int get_obj_i32(data_obj *cv, int32_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_I32)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (int32_t) obj_get_value(cv); return 1;};
    int get_obj_u32(data_obj *cv, uint32_t *val){ int ret; if(cv == NULL || val == NULL) return 0; if ((cv->dtype != TYPE_INVALID) && (cv->dtype != TYPE_U32)) return 0; ret = obj_request(cv, cv->read_to); if(ret == 0) return 0; *val = (uint32_t) obj_get_value(cv); return 1;};
    

    So was mag ich nicht, so was möchte ich nicht "debuggen", weiss nicht, wie es die anderen sehen. Oder wahrscheinlich gehöre ich einfach zu der Menge der Programmierer, die schlechte Bugfixer sind und fremden Code nicht lesen können oder wollen, wie hier angesprochen http://www.c-plusplus.net/forum/viewtopic-var-t-is-267345-and-highlight-is-.html
    Ausserdem greift das Argument "viel Tipparbeit einsparen" bei mir nicht, weil ich einen anderen Editor benutze, der einen Ruf hat, kompliziert zu sein, und den ich hier nicht nennen möchte, weil sich sonst sofort eine Gruppe anderer Leute melden würde, die einen anderen Editor benutzen, der einen Ruf hat, ein Betriebsystem zu sein, in dem es an einem guten Editor mangele 🙂



  • @abc.w:

    ich hab doch gesagt, ich hab es leicht abgeändert und Sachen entfernt, die dem Bsp nicht helfen, deshalb die fehlende \ am Ende.

    Ich habe viele Module, die eine get und set Funktion für jedes Datentyp anbietet. Leider sieht diese get/set Funktion in allen Fällen gleich, bis auf den Datentypen. Wieso soll ich redundanten Code (der nur an sehr wenigen Stellen sich ändert) zig-Mal schreiben? Und wenn die Sematik leicht verändert, dann muss ich jede einzelne Funktion verändern. Mit meinem Makro verändere ich nur an einer einzigen Stelle (und sowas musste ich schon ein Paar machen).

    Die Idee hab ich aus GTK geklaut, dort gibt (der gab es) solche Makros und fand es angenehm.

    @jizzerr:

    Makros sind keine Funktionen sondern eine reine *dumme* (fast) 1:1 Textersetzung. Dein Problem wirst du mit Makros NICHT gescheit lösen, höf auf deine Zeit damit zu verschwenden, dafür sind Makros nicht da.



  • Zeus schrieb:

    #include <stdio.h>
    
    void main()
    {
        double base = 2;
        int exp = 3;
        printf("Ergebnis: %3f", (double atemp = base; for(;exp>0;exp--)base*=atemp;));
    }
    

    Ich kann kein C - sag mir was an dieses C Programm nicht stimmt.

    Error 1 error C2146: syntax error : missing ')' before identifier
    Error 2 error C2065: 'atemp' : undeclared identifier
    Error 3 error C2106: '=' : left operand must be l-value
    Error 4 error C2143: syntax error : missing ')' before ';'
    Error 5 error C2065: 'atemp' : undeclared identifier
    Error 6 error C2059: syntax error : ')'
    Error 7 error C2059: syntax error : ')'

    Deklarationen in einer Anweisung sind das Problem



  • @jizzerr
    Hast du nicht gemerkt, dass ich den Präprozessor gespielt habe?



  • Ok



  • Nochmal eine Frage. Um welches Zeichen in der ASCII-Tabelle handelt es sich am ende eines Strings? dez 0 oder dez 48 ? Was meint Null-byte bzw. NULL in C ?


  • Mod

    jizzer schrieb:

    Nochmal eine Frage. Um welches Zeichen in der ASCII-Tabelle handelt es sich am ende eines Strings? dez 0 oder dez 48 ? Was meint Null-byte bzw. NULL in C ?

    0 natürlich. Sonst könnte man ja keine '0' im String haben.


Anmelden zum Antworten