C ++: ошибка компилятора при сравнении указателей с использованием макросов - PullRequest
1 голос
/ 01 января 2012

Я определил пользовательский макрос assert.Это отлично работает для всех других сравнений.Тем не менее, я получаю ошибку компилятора:

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 для этого случая, мне любопытно, почему эта ошибка компилятора генерируется.

Ответы [ 4 ]

8 голосов
/ 01 января 2012

Проблема в том, что 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).

3 голосов
/ 01 января 2012

Изменение

if(!condition)

Для

if(! (condition) )

Как вы это сделали, ! применяется к первому указателю в сравнении, а не к результату сравнения, он имеет более высокий приоритет, чем ==.

Вы всегда должны заключать параметры макроса в скобки, чтобы избежать подобных проблем. Иногда компилятор не предупреждает вас, и вы будете слушать по ночам в поисках ошибки.

1 голос
/ 01 января 2012

Поставьте скобку вокруг условия в 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) строй.)

0 голосов
/ 01 января 2012

Попробуйте

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