简体   繁体   English

C ++:使用宏比较指针时发生编译器错误

[英]C++: Compiler Error While Comparing Pointers using Macros

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. 使用下面显示的宏(DWASSERT)比较指针时,如下面的代码所示。

#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. 尽管我可以避免在这种情况下使用DWASSERT,但是我很好奇为什么会生成此编译器错误。

The problem is that DWASSERT(ptr1 == ptr2, ... gets expanded to 问题是DWASSERT(ptr1 == ptr2, ...被扩展为
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. !ptr1 == ptr2等效于(!ptr1) == (ptr2) ,并且由于!ptr1是整数类型,而ptr2是指针类型,因此会出现错误。

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. 另外,请记住,以任意方式将printf用作任意字符串是一种不好的主意 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) . 您应该使用puts(x)printf("%s", x)

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. 有时,编译器不会警告您,并且您会在晚上寻找问题的消息。

Put parenthesis around the condition in the if in the macro: 将括号放在条件中的if宏中:

#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.) (如果确实需要使用宏,则应在其中创建一个匿名块,并将条件的评估结果保存在临时的bool 。这通常是通过do { ... } while(0)构造完成的。)

尝试

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM