【问题标题】:C++: Compiler Error While Comparing Pointers using MacrosC++:使用宏比较指针时出现编译器错误
【发布时间】:2012-01-31 05:20:33
【问题描述】:

我定义了一个自定义断言宏。这适用于所有其他比较。但是,我得到编译器错误:

ISO C++ forbids comparison between pointer and integer

当使用如下所示的宏 (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;
}

虽然我可以简单地避免在这种情况下使用 DWASSERT,但我很好奇为什么会生成此编译器错误。

【问题讨论】:

  • 尝试将比较表达式放在括号内,例如:DWASSERT( ( ptr1 == ptr2 ), "Pointers not equal!\n" );
  • 在编写宏时,当使用其中一个宏参数时,默认情况下应将其包裹在括号中。仅当您知道必须删除它们(以及为什么)时才删除括号。有一些宏的用途是添加括号会导致问题,但绝大多数情况相反。
  • 您还应该包装这个宏,这样它就不会以意想不到的方式与if/else 语句交互:stackoverflow.com/questions/923822/…

标签: c++ macros assert


【解决方案1】:

问题是DWASSERT(ptr1 == ptr2, ... 被扩展为
if(!ptr1 == ptr2){ printf(...

你知道发生了什么吗? !ptr1 == ptr2 等价于(!ptr1) == (ptr2),由于!ptr1 是整数类型而ptr2 是指针类型,所以您会得到错误。

您需要做的是解决这个问题,将您的宏定义更改为:

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

另外,请记住,以任意字符串作为格式使用printf 是一个坏主意。在某些时候,有人会给你一个带有% 的字符串,事情就会中断。您应该使用 puts(x)printf("%s", x) 之类的东西。

【讨论】:

    【解决方案2】:

    改变

    if(!condition)
    

    if(! (condition) )
    

    按照您的方式,! 应用于比较中的第一个指针,而不是比较结果,它的优先级高于==

    您应始终将宏参数括在括号中以避免类似问题。有时编译器不会警告你,你会为了寻找错误而费尽周折。

    【讨论】:

      【解决方案3】:

      在宏中的if 的条件周围加上括号:

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

      编译器正在查看:

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

      解释为:

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

      这不是你想要的。但是您确实应该为此使用适当的功能-条件可能会使用您的宏进行两次评估。在某些情况下,第二次测试可能会产生与第一次不同的结果,这会产生非常令人惊讶的结果。

      int i = -1;
      
      DWASSERT(++i, "will I assert?");
      

      (如果你真的必须使用宏,你应该在其中创建一个匿名块,并将条件评估保存在一个临时的bool 中。这通常使用do { ... } while(0) 构造来完成。)

      【讨论】:

      • 断言是我在其中使用宏而不是函数的少数几个地方之一(在回溯中更容易),但由于您提到的原因,我会确保条件只评估一次。
      【解决方案4】:

      试试

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

      【讨论】:

      • 治标不治本。
      • 我想这取决于谁在使用它。对于这样的事情,我强制将条件语句括起来。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-03
      • 2011-01-16
      • 1970-01-01
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多