Macros und komma Probleme



  • Hallo,
    ich hab nen kleines Problem was den gebrauch von Kommas in Makros anbelangt:

    #include <stdlib.h>
    #define tollesBit G6
    
    #define A0 a,0
    #define A1 a,1
    #define A2 a,2
    #define A3 a,3
    //das würde ich mit allen bits von A0-G7 machen
    #define G6 g,6
    #define G7 g,7
    
    #define setBit(addr, bit) addr |= 1 << bit
    #define clearBit(addr, bit) addr &= -(1 << bit)
    int main()
    {
    	int8_t a, b, c, d, e, f, g;
    	setBit(c, 4); //setzt das bit 4 im byte c, tut
    
    	setBit(tollesBit);
    
    /*	setBit(tollesBit) sollte das bit 6 im byte g setzen, das tut aber net:
    
    	test.c: In function ‘main’:
    	test.c:18:18: error: macro "setBit" requires 2 arguments, but only 1 given
    	test.c:18:2: error: ‘setBit’ undeclared (first use in this function)
    
    	ich weiß ich könnte statt 
    	#define tollesBit G6
    	setBit(tollesBit)
    
    	auch
    
    	#define byteDesTollenBits g
    	#define bitDesTollenBits 6
    	setBit(byteDesTollenBits, bitDesTollenBits);
    
    	machen(das tut auch), aber das wäre sehr aufwendig, 
    	denn ich möchte wenns geht ändern können welches 
    	bit toll ist ohne 2 #defines zu ändern
    	(für alle die sich fragen was "tollesBit" im Programm sein soll: 
    	das ist der Anschluss eines bestimmten sensors, a,b,c,d,e,f,g sind die IO-Register)
    */
    }
    

    Ich hoffe ihr könnt mir helfen.



  • Makros sind reine Textersetzung.

    Sowas ist möglich

    #define min(a,b) ((a) < (b) ? (a) : (b))
    #define add(x,y) ((x) + min((x),(y)))
    
    add(3,4);
    

    und wird zu

    ((3) + (((3)) < ((4)) ? ((3)) : ((4))));
    

    ausgwertet. Aber deine Makros scheinen für den Präprozessor zu schlau/komplex zu sein, ich kann mir vorstellen, dass der Präprozessor wie folgt vorgeht:

    - aha, ein Makro: setBit
      - setBit braucht 2 Parameter
      - 1. Parameter ist tollesBit (C-Präprozessor weiß noch nicht, dass
        tollesBit ein Makro ist. Das wird er beim 2. Durchlauf ersrt erfahren)
      - 2. Parameter ist ??? nicht angegeben --> error: macro "setBit" requires 2 arguments, but only 1 given
    

    Vielleicht lässt sich was mit __VA_ARGS__ etwas basteln (siehe http://stackoverflow.com/questions/12447557/can-we-have-recursive-macros oder http://stackoverflow.com/questions/985403/seeing-expanded-c-macros) aber ganz ehrlich, damit wird dein Code super unübersichtlich, das solltest du nicht machen.


  • Mod

    Die Zuordnung der Argumente zu einem Fuktionsmakro erfolgt, bevor die Argumente expandiert werden. Es wird daher ein zusätzlicher Zwischenschritt benötigt (nicht untypisch fpür den Präprozessor).
    z.B. so

    #include <stdlib.h>
    #define tollesBit G6
    
    #define A0 a,0
    #define A1 a,1
    #define A2 a,2
    #define A3 a,3
    //das würde ich mit allen bits von A0-G7 machen
    #define G6 g,6
    #define G7 g,7
    
    #define setBit_(addr, bit) addr |= 1 << bit
    #define setBit(...) setBit_(__VA_ARGS__)
    //                          ^^ Trick: die Zuordnung zu den setBit_-Parametern erfolgt erst *nachdem* __VA_ARGS__ expandiert wurde
    #define clearBit(addr, bit) addr &= -(1 << bit)
    int main()
    {
        int8_t a, b, c, d, e, f, g;
        setBit(c, 4); //setzt das bit 4 im byte c, tut
    
        setBit(tollesBit);
    }
    

  • Mod

    Gibt es einen tieferen Grund, hierfür keine Funktion zu benutzen? Kann man auch inline machen, wenn man um Overhead besorgt ist. Zumal das Makro auch prompt genau die Dinge falsch macht, die Anfänger typischerweise in Makros falsch machen:

    #define setBit(addr, bit) addr |= 1 << bit
    setBit(a, x < y ? 3:4);
    // ->
    a |= 1 << x < y ? 3:4;  // Oh weh, das war bestimmt nicht gemeint!
    

    Schlechter Start für den Makrofreund, wenn man das schon falsch macht.


Anmelden zum Antworten