0

Let's start with the code and the error.

#define BitMap_getMask(range)           (((~(unsigned int)0>>(31-range.b+range.a))<<range.a))
#define BitMap_get(x, range)            (x & BitMap_getMask(range))
#define awesome (range){4,6}
...................
printf("%08x\n", BitMap_get(0xEEEEEEEE, awesome));

Now the error from the compiler. Line 29, the line with the printf.

error: macro "BitMap_getMask" passed 2 arguments, but takes just 1
error: 'BitMap_getMask' undeclared (first use in this function)

I'm working on a small library which will help me with bitwise operations. When trying to use a macro within another macro I am getting this error.

6
  • 1
    why do you have this #define awesome (range){4,6} what is it supposed to do? Commented Jan 21, 2015 at 17:34
  • Why are you even using macros for this ? Why not just use functions (inline if necessary) ? Commented Jan 21, 2015 at 17:34
  • The first compiler error is pretty clear. So what part of your code is calling BitMap_getMask with two arguments? Commented Jan 21, 2015 at 17:43
  • 1
    @DavidGrayson He is most likely suffering from a bad macro expansion, so that what looks like a single parameter is actually 2 by the time the pre-processor expands everything. iharob's answer is headed that way by adding additional parentheses to clarify things Commented Jan 21, 2015 at 17:45
  • 1
    I think the problem is that you are trying to return something from the first macro (?) And TECHNICALLY macros don't return anything; use a function. Commented Jan 21, 2015 at 18:32

2 Answers 2

3

When range is expanded to {4,6} and passed to BitMap_getMask, what you're getting is BitMap_getMask({4,6}) which is 2 arguments, whereas BitMap_getMask expects 1 argument.

Furthermore, the pre-processor only does text replacement for these macros. It is unaware of type. It will replace every instance of text "range" with text "{4,6}" so you don't have a type (struct range) or instance of a type, that you can use, just some text, so "range.a" and "range.b" are also not going work; they would result something like "{4,6}.a" and "{4,6}.b"

Not valid C.

C99 supports inline functions, and there is almost no excuse for using pre-processor macros in C these days. They are trouble (one good use of course is include guards). Inline functions are in the domain of the compiler and properly type-checked.

struct awesome
{
    unsigned int a;
    unsigned int b;
};

...

static inline unsigned int BitMap_get(unsigned int x, awesome range) 
{
    return (x & BitMap_getMask(range));
}

static inline unsigned int BitMap_getMask(awesome range) 
{
    return (((~(unsigned int)0>>(31-range.b+range.a))<<range.a));
}

...

awesome range = 
{
    .a = 4,
    .b = 6,
};

unsigned int x = 0xEEEEEEEE;
unsigned int bm = BitMap_get(x, awesome);
...
Sign up to request clarification or add additional context in comments.

Comments

3

This might be what you need

#define BitMap_getMask(range) \
   (((~(unsigned int) 0 >> (31 - (range).max + (range).min)) << (range).min))

#define BitMap_get(x, range) \
   ((x) & BitMap_getMask(range))

#define awesome \
   ((struct {int min; int max;}){4, 6})

the error was due to the expansion of {4, 6}.

2 Comments

when using C macros, each argument should always be surrounded by parens '(' and ')' in the expansion of the macro. Without the parens, very subtle errors in the expansion can occur, where those errors are very difficult to debug.
@user3629249 In fact being paranoid with parentheses in macros seems very good to me, it avoids a lot of problems.

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.