确定是否将相同的指针传递给宏

Determine if same pointers are passed to a macro

本文关键字:指针 是否      更新时间:2023-10-16

有一组宏,用于调试,日志记录,堆栈跟踪显示等。其中一个是:

#define ASSERT_IF_NULL_2(_ptr1, _ptr2)  
    ASSERT(_ptr1);  
    ASSERT(_ptr2);

这是我所写的宏的简化版本。如果断言(运行时)失败,我有自定义断言对话框,将空检查失败记录到日志文件中。宏也被编写成在编译时检查非指针(static-assert)。

现在,我正在寻找一些静态断言来检查两个指针是否实际上相同。例子:

int* ptr;
ASSERT_IF_NULL_2(ptr, ptr);

应该引发编译器错误,因为宏的两个参数相同。我不关心指针是否指向相同的内存(因为那是运行时)。

我试过这样的表达:

int xx;
xx = 1 / (ptr-ptr);
xx = 1 / (&ptr - &ptr);

它们都不会给出除零编译错误。此外,我还尝试了采用void*模板参数的模板:

template<void* T>
class Sample{};

但是不允许将局部变量指针传递给模板非类型参数。

我使用的是VC9,它不支持constexpr关键字(即使VS2012也不支持)。我尝试使用'const'代替,它不会抛出错误。我还使用表达式作为数组大小,其中总是导致错误。

int array[(&ptr - &ptr)]; // Even with ptrdiff_t

好的,解决方案很简单。使用static_assert和Stringizing Operator (#):

#define ASSERT_TWO(a,b) static_assert((void*)#a != (void*) #b, "'" #a  "' and '" #b "' are same variables passed to ASSERT_TWO.") 
演示:

int *global;    
int main()
{
    int *local;
    ASSERT_TWO(global, local);  //should pass
    ASSERT_TWO(local, global);  //should pass
    ASSERT_TWO(global, global); //should fail
    ASSERT_TWO(local, local);   //should fail
    (void)local; //suppress unsused warning!
}

导致非常有用的错误信息:

main.cpp: In function 'int main()':
main.cpp:18:5:错误:静态断言失败:'global'和'global'是传递给ASSERT_TWO的相同变量。
main.cpp:19:5:错误:静态断言失败:'local'和'local'是传递给ASSERT_TWO的相同变量。

在线演示。

希望对你有帮助。

我记得这不会帮助你,因为你正在使用VC9,但我保留这个答案,因为它可能会帮助别人。到目前为止,您可以使用其他产生重声明错误的解决方案,与static_assert消息相比,这是不太有用的错误消息。

你想检查是否相同的名称传递给两个参数,对吧?那么这个简单的技巧就起作用了

#define ASSERT_IF_NULL_2(_ptr1, _ptr2)
{
    int _check_##_ptr1;
    int _check_##_ptr2;
}
ASSERT(_ptr1);
ASSERT(_ptr2);
int main ()
{
    int* ptr1;
    int* ptr2;
    ASSERT_IF_NULL_2 (ptr1, ptr1); // error: redeclaration of `int _check_ptr1'
    ASSERT_IF_NULL_2 (ptr1, ptr2); // OK
}

EDIT (By OP, Ajay):

在Visual c++编译器中,我们可以使用MS特定的关键字__if_exists通过static-assert给出错误:

 #define ASSERT_IF_NULL_2(_ptr1, _ptr2)
    {
        int _check_##_ptr1;
        __if_exists(_check_##_ptr2) 
             STATIC_ASSERT(false, "Same pointer passed twice")
    }

由于static_assert关键字在vs2010之前的编译器中不存在,因此可以使用自定义编写的STATIC_ASSERT

您是否试图检查指针是否指向相同的内存,或者它们是否指向相同的值?

第一种情况

xx = 1 / (ptr-ptr);

xx = 1 / (*ptr-*ptr);

不妨试一下:

ASSERT_IF_NULL(ptr1 == ptr1);
ASSERT(ptr1 != ptr2)

正如Nawaz指出的那样,如果你想要一个编译错误,那么试试这个:

1/(ptr1 != ptr2);
1/static_cast<int>(ptr1 != ptr2);
static_assert(ptr1 != ptr2, "Pointers are different")       //if you dont use c++0x look here:http://stackoverflow.com/a/1664651/258418