C Concatenating macros using a variable - is this possible?

I am trying to define a macro to create the name of a token containing a variable.

Basically, I am trying to do this:

#define GLUER(x,y,z) x##y##z #define PxDIR(x) GLUER(P,x,DIR) int main() { int port; port = 2; PxDIR(port) |= 0x01; } 

I hope to generate a P2DIR token in the above expression, but according to my compiler, it generates a PportDIR token, which is NOT what I wanted. Any help here? Or am I trying to make it impossible?

+6
c c-preprocessor concatenation token stringification
source share
4 answers

I do not think that what you are trying to do is possible. C macros are preprocessor macros that extend before compilation. The port variable is not set until runtime.

+6
source share

It's impossible. C preprocessors work by processing tokens , and they do not perform any permissions or replacements that would require knowledge of the mechanics of the language (except for basic arithmetic using integer literals from the top of my head). Consider, for example, documents for the GCC preprocessor regarding tokenization . Only the compiler will know what to do with the variable "port".

One solution is to do something like:

 #define PxDIR(var, portnum) do { \ var = portnum; \ P##portnum##DIR |= blah; \ } while(0) 

... and later ...

 int port; PxDIR(port, 2); 

I leave it for you to make it not as ugly or hacked as it is here (and more general, depending on what you need) :)

+3
source share

... or just make PORT also a macro:

 #define PORT 2 #define GLUER(x,y,z) x##y##z #define PxDIR(x) GLUER(P,x,DIR) int main() { PxDIR(PORT) |= 0x01; return 0; } 
+2
source share

What you are trying to do does not make sense.

 #define GLUER(x,y,z) x##y##z #define PxDIR(x) GLUER(P,x,DIR) int main() { int port; port = 2; PxDIR(port) |= 0x01; } 

The preprocessor starts at (before) compile time. Therefore, he does not know anything about the contents of the port variable. The preprocessor requires that any values ​​passed as arguments to macros be constants. For example, you can do the following:

 #define GLUER(x,y,z) x##y##z #define PxDIR(x) GLUER(P,x,DIR) int main() { PxDIR(2) |= 0x01; //setup port 2 } 

Otherwise, if you want to pass a variable to this macro, there really is the only way to make sure that the code for this is explicitly generated:

 #define GLUER(x,y,z) x##y##z #define PxDIR(x) GLUER(P,x,DIR) uint16_t* get_port_pointer(uint8_t port_id) { if (port == 0) { return &PxDIR(0); } else if (port == 1) { return &PxDIR(1); } else if (port == 2) { return &PxDIR(2); } else if (port == 3) { return &PxDIR(3); } else { return &0; } } int main() { int port; port = 2; *(get_port_pointer(port)) |= 0x01; } 

Thus, we provide access to all ports from 0 to 3. In addition, now we must monitor the return of null pointers from the get_port_pointer function.

0
source share

All Articles