سؤال

I have some macros to define bit fields in registers easily (I use these for read, modify, write operations, set, gets etc). I'm getting a compiler error that I don't understand.

// used just for named arguments -- to make the values more clear when defined
#define FLDARGS(dwOffset, bitStart, bitLen) dwOffset, bitStart, bitLen
// extract just the dwOffset part
#define FLD_DWOFFSET(dwOffset, bitStart, bitLen) dwOffset

// define a bit field
#define CFGCAP_DEVCTRL FLDARGS(2, 16, 4)

// in a function:

uint32_t dwAddr = addr/4;
// compare just the dwOffset part
if(dwAddr == FLD_DWOFFSET( CFGCAP_DEVCTRL ))
{
 // do something
}

I expected this to expand like: CFGCAP_DEVCTRL = 2, 16, 4

FLD_DWOFFSET( CFGCAP_DEVCTRL ) = 2

I get the gcc error:

error: macro "FLD_DWOFFSET" requires 3 arguments, but only 1 given
      if(dwAddr == FLD_DWOFFSET( CFGCAP_DEVCTRL ))
                                                ^
error: ‘FLD_DWOFFSET’ was not declared in this scope
      if(dwAddr == FLD_DWOFFSET( CFGCAP_DEVCTRL ))

Any help? Thanks.

هل كانت مفيدة؟

المحلول 3

The other answers are correct in telling me why I can't do what I want to do. FLD_DWOFFSET is being evaluated with a single arg that isn't being expanded.

Here's my solution :

static inline uint32_t FLD_DWOFFSET(int dwOffset, int bitStart, int bitLen){return dwOffset;}

Hopefully this performs the same with optimization. Since it's a function, the macro argument (which expands to 3 args) is expanded before calling it.

نصائح أخرى

Let's see how your macros are going to be processed:

if(dwAddr == FLD_DWOFFSET( CFGCAP_DEVCTRL ))

First, it tries to substitute the outermost macro, which is FLD_DWOFFSET. But it requires 3 arguments, when you only provide 1 (your inner macro isn't parsed at that moment yet). The preprocessor can't go any further, hence the error.

There is more relevant info here: http://gcc.gnu.org/onlinedocs/cpp/Macro-Pitfalls.html#Macro-Pitfalls

The macro pass expands macros in the order they're found. The first macro to be found is FLD_DWOFFSET( stuff ), which only sees one argument CFGCAP_DEVCTRL, and as a result cannot expand the FLD_DWOFFSET macro. It does not try to expand further macros until the current expansion is complete - in other words, it won't recognize that CFGCAP_DEVCTRL is a macro until it's finished expanding FLD_DWOFFSET, but it won't do that because you haven't provided enough arguments...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top