How to define a macro of two tokens in Cpp - c-preprocessor

In my Arduinoc (cpp) code, I have these macros that set/clear bit y of register x:
#define SET(x,y) x |= (1 << y)
#define CLEAR(x,y) x &= ~(1<< y)
In several places I then use:
CLEAR(PORTB,7)
or
SET(PORTB,7)
I would like to define a macro to be PORTB,7 so it only appear once, in a header file, not all over my code. (I show only one example, but I have several conbinations of PORTx,N in my code).
I tried:
#define CLOCK PORTB,7
#define CLOCK_HIGH SET(CLOCK)
but it then fails to build with:
error: macro "SET" requires 2 arguments, but only 1 given CLOCK_HIGH; delay(DELAY); CLOCK_LOW; delay(DELAY);
Is there a way to achieve that?

You must first expand the macro inside. Ie. do another pass. Your code may look like this:
#define SET(x,y) do{ (x) |= (1u << (y)); }while(0)
#define CLEAR(x,y) do{ (x) &= ~(1u << (y)); }while(0)
#define HIGH(a) SET(a) // another empty pass, just forward
// the `a` is expanded and the second `SET` takes two arguments
// or better, but not fully compliant:
// #define HIGH(...) SET(__VA_ARGS__)
#define CLOCK PORTB, 7
#define CLOCK_HIGH() HIGH(CLOCK)
int main() {
int PORTB;
CLOCK_HIGH();
}
As a good measure research about macro pitfalls and research good practices when writing macros..

Related

Assigning value in C macro

Is it ok to assign a value in a C macro (i.e. have an lvalue in a macro)? For example, I would like to set a bit of a number to 1 based on the specified bit position. Is it ok to do this:
#define SET_BIT(data, pos) ((data) |= (1U << (pos)))
I've tested this and it works, but I feel like I'm walking on thin ice here and if I get used to macros like this, I would eventually run into problems.
Macros won't exist once the preprocessor has finished expanding them in the code. If you have a statement like
SET_BIT(some_data, some_pos);
then it will be replaced by
((some_data) |= (1U << (some_pos)));
in the code that is parsed and compiled.
In short, doing assignments in macros is perfectly fine.
The problem with the first SET_BIT_TO_VAL macro:
#define SET_BIT_TO_VAL(data, pos, val) (CLEAR_BIT(data, pos); (data) |= (1U << (pos)))
is that you put statements inside parentheses, like they were expressions. So that will not build.
The common way to group statements in a macro is to wrap them in a do { ... } while(0) loop:
#define SET_BIT_TO_VAL(data, pos, val) \
do { \
CLEAR_BIT(data, pos); \
SET_BIT(data, pos); \
} while (0)

Use #define to specify multiple paramaters [duplicate]

I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.

#define a tuple in C

I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.

Setting a flag in C as elegantly as in assemby language

Flags handling in C feels cumbersome, compared to assembly.
I am looking for a way to make the C code as readable as assembly.
In Assembly:
#define powerOn flagsByte,0
...
bsf powerOn ; Turn on the power
bcf powerOn ; Turn off the power
btfsc powerOn ; If the power is on...
In C:
flagsByte |= (1 << 0) ; // Turn on the power
flagsByte &= ~(1 << 0) ; // Turn off the power
if (flagsByte & (1 << 0)); // If the power is on...
In C, with a macro:
#define BIT_SET(var,bitNo) (var |= (1<<(bitNo)))
BIT_SET(flagsByte,0) ; // Turn on the power
That works, but it's still not as clean as in assembly.
I'd love to do:
#define powerOn flagsByte,0
BIT_SET(powerOn) ; // Turn on the power
But that doesn't work, because it expands to:
flagsByte,0 |= (1<<())
instead of:
flagsByte |= (1<<(0))
Question:
Is there an elegant way in C to set, clear or test a flag that is defined as follows?
#define powerOn flagsByte,0
Personally, I prefer the bit-field syntax, and without macros since my flags are almost always inside structs anyway. However, if you insist on writing assembler in C, here's how:
/* We need to indirect the macro call so that the pair of arguments get expanded */
#define BITSET_(f,i) do{f|= 1<<(i);}while(0)
#define BITCLR_(f,i) do{f&=~(1<<(i));}while(0)
#define BITCHK_(f,i) ((f)&(1<<(i)))
#define BITSET(fi) BITSET_(fi)
#define BITCLR(fi) BITCLR_(fi)
#define BITCHK(fi) BITCHK_(fi)
/* Define the flag container and bit number as per OP */
#define poweron flags1,0
#define warnuser flags7,4
/* Sample uses */
BITSET(poweron);
BITCLR(warnuser);
/* Since BITCHK expands to a parenthesized expression, I can get away with
* leaving out the parentheses in the if statement. Not saying that's a good
* idea or anything.
*/
if BITCHK(poweron) BITSET(warnuser);
If you have gcc, you can verify this with gcc -E flag_macros.c
Here's a set of macros closely matching your assembly example:
#define powerOn 0
#define someotherfield 1
#define BITMASK(field) (1u << (field))
#define SET(field) do { flagsByte |= BITMASK(field); } while(0)
#define CLR(field) do { flagsByte &= ~BITMASK(field); } while(0)
#define TEST(field) (flagsByte & BITMASK(field))
/* Use examples */
SET(powerOn);
CLEAR(powerOn);
if (TEST(powerOn)) {
// Danger!
}
Here's a variant that allows you to include the variable in the particular field definition. It's a bit tricky as it involves argument prescan
#define powerOn flagsByte,0
#define someotherfield flagsByte,1
#define BITMASK(field) (1u << (field))
#define _SET(var, field) do { var |= BITMASK(field); } while(0)
#define SET(x) _SET(x)
/* Use examples */
SET(powerOn);
You could #define powerOn flagsByte |= (1 << 0); and then just use it like a statement. As in
// do stuff...
powerOn; // Turn power on.
// do stuff...
With GCC you can define so-called bit fields and manipulate them like struct members:
struct flagsByte
{
unsigned int powerOn: 1; /* single bit */
};
flagsByte.powerOn = 0;
flagsByte.powerOn = 1;
Building upon this, it is possibile to define a couple of trivial macros, reminiscent of Assembly:
#define bsf(X) flagsByte.(X) = 1
#define bcf(X) flagsByte.(X) = 0
and simply write
bsf(powerOn); /* set flag */
bcf(powerOn); /* clear flag */
Unfortunately, this is not applicable to every C compiler.
You do this with a second expansion.
~/sandbox/20$ cat >t.c
#define BITSET_INNER(a,b) a |= (1<<b)
#define BITSET(spec) BITSET_INNER(spec)
#define f1 flagword,3
BITSET(f1)
~/sandbox/20$ cc -E t.c
# 1 "t.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "t.c"
flagword |= (1<<3)
Add token pasting and a with a strong gorge you can get some extremely gratifying results out of the C preprocessor.
You could just define some constants, not using the preprocessor but enums for fewer surprises:
enum flags{
powerOn = 1<<0,
powerMask = ~powerOn,
/*...*/
};
And use them like this:
flagsByte |= power;
flagsByte &= ~power;
flagsByte &= powerMask; /* same as previous line */
A good rule of thumb in C (and C++): Do not use the preprocessor if you can avoid it.
Anyway, if you can live with the inherent implementation-definedness of bitfields, use bitfields as Roberto Reale proposes.

C pre-processor macro expansion

I'm trying to do (what I would have thought) was a simple macro expansion
#define CLEAR_DIGIT(a,b) iconMap[a] &= ~(b)
#define R1 4, 16
CLEAR_DIGIT(R1);
Now I would expect that to expand to CLEAR_DIGIT(4,16) which expands to iconMap[4] &= ~16
However, it doesn't... If I make CLEAR_DIGIT a function:
void ClearDigit(unsigned char a, unsigned char b)
{
iconMap[a] &= ~b;
}
#define R1 4, 16
ClearDigit(R1);
then it works fine, so R1 being expanded out to the two arguments isn't an issue... Is there any way of forcing it to expand R1 before doing the macro function expansion?
You could use a helper macro. See also double-stringize problem
#define CLEAR_DIGIT_HELPER(a,b) iconMap[a] &= ~(b)
#define CLEAR_DIGIT(x) CLEAR_DIGIT_HELPER(x)
#define R1 4, 16
CLEAR_DIGIT(R1);

Resources