0

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.

0

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

From your link: "Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens." Doesn't that mean that CFGCAP_DEVCTRL should be expanded first, and then FLD_DWOFFSET evaluated? http://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html#Argument-Prescan
No, macros are expanded when they are actually used in code. CFGCAP_DEVCTRL is just a macro definition. It will not be expanded until it's used.
1

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...

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.