Bit manipulation in nested MACRO leads to `lvalue required as left operand of assignment` why?

Viewed 105

I am trying to manipulate certain bit( bit 1) using the following nested macros, but I am running into the error lvalue required as left operand of assignment

My code is as follows

#define CONTROL1 (*((unsigned int volatile *) 0x00AA))
#define CONTROL2 (*((unsigned int volatile *) 0x00BB))

#define XC_PIPE(pipe) (unsigned int volatile *)( (pipe) == 0 ?  (CONTROL1) : (CONTROL2) )
    
#define XC_ENABLE(pipe) ( ( XC_PIPE(pipe) ) |= (1<<(1)))

#define XC_DISABLE(pipe) ( ( XC_PIPE(pipe) ) &= ~(1<<(1)))

#define XC_MODULE_TOGGLE(on,pipe) ( (on) == true ?  (XC_DISABLE(pipe)) : (XC_ENABLE(pipe)) )

and I call it like this

XC_MODULE_TOGGLE(false,0);

How can I avoid this error?

2 Answers

You are missing the necessary indirection in

#define XC_ENABLE(pipe) ( ( XC_PIPE(pipe) ) |= (1<<(1)))
#define XC_DISABLE(pipe) ( ( XC_PIPE(pipe) ) &= ~(1<<(1)))

Please change to

#define XC_ENABLE(pipe) ( *( XC_PIPE(pipe) ) |= (1<<(1)))
#define XC_DISABLE(pipe) ( *( XC_PIPE(pipe) ) &= ~(1<<(1)))

The definition of XC_PIPE() is flawed: the cast (unsigned int volatile *) is incorrect as both CONTROL1 and CONTROL2 already dereference the absolute address. To ensure that XC_PIPE can be use as an L-value, you should write it this way:

#define XC_PIPE(pipe) (*((pipe) == 0 ? &(CONTROL1) : &(CONTROL2)))

You can remove some redundant parentheses too and prevent warnings about unused values by making XC_ENABLE() and XC_DISABLE() void expressions:

#define CONTROL1  (*(unsigned int volatile *)0x00AA)
#define CONTROL2  (*(unsigned int volatile *)0x00BB)

#define XC_PIPE(pipe) (*((pipe) == 0 ? &(CONTROL1) : &(CONTROL2)))

#define XC_ENABLE(pipe)  (void)(XC_PIPE(pipe) |= (1 << 1))
#define XC_DISABLE(pipe) (void)(XC_PIPE(pipe) &= ~(1 << 1))

#define XC_MODULE_TOGGLE(on, pipe)  ((on) ? XC_DISABLE(pipe) : XC_ENABLE(pipe))
Related