1

I have defined a custom assert macro. This works fine for all other comparisons. However, I get the compiler error:

ISO C++ forbids comparison between pointer and integer

when using the macro shown below (DWASSERT) to compare pointers as in the code below.

#define DWASSERT(condition,printstatement)  if(!condition){ printf(printstatement); assert(condition); }

#include <stdio.h>

int main()
{
    int target = 0;
    int* ptr1 = &target;
    int* ptr2 = &target;

    //Normal comparison works fine
    if(ptr1 == ptr2)
        printf("Equal");

    //Comparison using Macro generates compiler
    //error on the next line
    DWASSERT(ptr1 == ptr2, "Pointers not equal!\n");
    return 0;
}

While I can simply avoid using DWASSERT for this case, I am curious as to why this compiler error is generated.

eboix
  • 5,113
  • 1
  • 27
  • 38
balajeerc
  • 3,998
  • 7
  • 35
  • 51
  • try placing the comparison expression inside parenthesis for example: `DWASSERT( ( ptr1 == ptr2 ), "Pointers not equal!\n" );` – Yaniro Dec 31 '11 at 21:58
  • When writing a macro, when one of the macro parameters is used it should be wrapped in parens by default. Only ever remove the parens if you *know* that they must be removed (and why). There are a few uses of macros where adding the parens causes problems, but the vast majority fall the other way. – Michael Burr Dec 31 '11 at 22:03
  • 2
    You should also probably wrap this macro so it doesn't interact in unexpected ways with `if`/`else` statements: http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we-define-a-macro – Michael Burr Dec 31 '11 at 22:23

4 Answers4

8

The problem is that DWASSERT(ptr1 == ptr2, ... gets expanded to
if(!ptr1 == ptr2){ printf(...

Do you see what's going on? !ptr1 == ptr2 is equivalent to (!ptr1) == (ptr2), and since !ptr1 is an integer type and ptr2 is a pointer type, you get your error.

What you need to do to fix this is to change your macro definition to:

#define DWASSERT(condition,printstatement)  if(!(condition)){ printf...

Also, keep in mind that it is a bad idea to use printf the way you have, with an arbitrary string as a format. At some point somebody will give you a string with a % in it and things will break. You should use something like puts(x) or printf("%s", x).

Gabe
  • 84,912
  • 12
  • 139
  • 238
3

Change

if(!condition)

To

if(! (condition) )

The way you did it, ! is applied to the first pointer in the comparison, not the comparison result, it has higher precedence than ==.

You should always enclose the macro parameters in parenthesis to avoid similar problems. Sometimes the compiler won't warn you and you'll be pulling your hears for nights looking for the bug.

littleadv
  • 20,100
  • 2
  • 36
  • 50
1

Put parenthesis around the condition in the if in the macro:

#define DWASSERT(condition,printstatement)  if(!(condition)){ printf(printstatement); assert(condition); }

The compiler is seeing:

if (!ptr1 == ptr2) { ... }

Which is interpreted as:

if ((!ptr1) == ptr2) { ... }

Which is not what you want. But you should really be using a proper function for this - the condition is potentially evaluated twice with your macro. There could be circumstances where the second test could yield different results from the first, which would have very surprising results.

int i = -1;

DWASSERT(++i, "will I assert?");

(If you really have to use a macro, you should create an anonymous block in it, and save the evaluation of the condition in a temporary bool. This is often done with a do { ... } while(0) construct.)

Mat
  • 202,337
  • 40
  • 393
  • 406
  • Assertion is one of the very few places where I use macros in rather than functions (easier in traceback) but I’d make sure that the condition was only evaluated once, for the reasons you mentioned. – Konrad Rudolph Dec 31 '11 at 22:02
0

Try

DWASSERT((ptr==ptr2), "Pointers not equal!\n");