Хакер, который я видел, - это использование &&оператора. Поскольку указатель "истинен", если он не равен нулю, вы можете сделать следующее, не изменяя условия:
assert(a == b &&"A is not equal to B");
Поскольку assertпоказывает условие, которое не удалось, оно также отобразит ваше сообщение. Если этого недостаточно, вы можете написать свою собственную myAssertфункцию или макрос, который будет отображать все, что вы хотите.
Другой вариант - перевернуть операнды и использовать оператор запятой. Вам нужны дополнительные круглые скобки, чтобы запятая не рассматривалась как разделитель между аргументами:assert(("A must be equal to B", a == b));
Кейт Томпсон,
3
Однако было бы неплохо иметь возможность печатать значения переменных, например:assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
Фрэнк
7
@Frank printfвозвращает ненулевое значение, если он что-то напечатал, поэтому вы могли бы сделать что-то подобное assert(a == b && printf("a (%i) is not equal to b (%i)", a, b)), хотя в этот момент вам, вероятно, следует написать свою собственную оболочку assert.
zneak 04
1
Плохой код! Я этого не понимаю! Если a == b ложно, выражение and также должно быть ложным, и, следовательно, строка не должна оцениваться.
ragnarius 07
1
@TUIlover, строковые литералы C работают не так; они являются константами времени компиляции, и их использование в этом контексте тривиально оптимизируется. Нет затрат на время выполнения.
zneak 09
46
Другой вариант - поменять местами операнды и использовать оператор запятой. Вам нужны дополнительные круглые скобки, чтобы запятая не рассматривалась как разделитель между аргументами:
assert(("A must be equal to B", a == b));
(это было скопировано из приведенных выше комментариев для лучшей видимости)
Это отличный подход, с одной крошечной проблемой, он будет отображать «предупреждение: левый операнд оператора запятой не действует» при компиляции в g ++ с помощью `-Wunused-value
v010dya
1
или с помощью макроса: #ifndef m_assert #define m_assert (expr, msg) assert ((msg, expr)) #endif
Szymon Marczak 03
Использование оболочки макроса позволяет избежать предупреждения gcc:#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Jander
25
Вот моя версия макроса assert, который принимает сообщение и распечатывает все в понятной форме:
Я немного запутался. Считается ли #Expr строкой для прямой подстановки? В чем разница между #Expr и Expr?
Минь Тран,
@MinhTran Предположим, что ваше условие утверждения - x == y. Затем Expr будет расширяться, if( !(x == y))и здесь проверяется условие, а #Expr расширяется в строковый литерал "x == y", который мы затем помещаем в сообщение об ошибке.
Евгений Магдалиц
К сожалению, это решение вызывает неопределенное поведение из-за использования зарезервированных идентификаторов.
Вы можете использовать это напрямую или скопировать код Boost. Также обратите внимание, что утверждение Boost - это только заголовок, поэтому вы можете просто получить этот единственный файл, если не хотите устанавливать все Boost.
«Поскольку читатель сообщения об ошибке assert все равно будет искать файл и строку в сообщении об ошибке», - только если они прилежны.
Джейсон С.
Только если они хотят исправить ошибку, вы имеете в виду ... какой глупый комментарий
метаморфоза
1
Нет. Чем проще вы сделаете так, чтобы люди увидели проблему, тем больше вероятность, что они примут меры.
Джейсон С.
пожимать плечами Не согласен.
метаморфоза
2
assert - это комбинация макроса / функции. вы можете определить свой собственный макрос / функцию, используя __FILE__, __BASE_FILE__и __LINE__т. д., со своей собственной функцией, которая принимает настраиваемое сообщение
Ответы:
Хакер, который я видел, - это использование
&&
оператора. Поскольку указатель "истинен", если он не равен нулю, вы можете сделать следующее, не изменяя условия:Поскольку
assert
показывает условие, которое не удалось, оно также отобразит ваше сообщение. Если этого недостаточно, вы можете написать свою собственнуюmyAssert
функцию или макрос, который будет отображать все, что вы хотите.источник
assert(("A must be equal to B", a == b));
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
printf
возвращает ненулевое значение, если он что-то напечатал, поэтому вы могли бы сделать что-то подобноеassert(a == b && printf("a (%i) is not equal to b (%i)", a, b))
, хотя в этот момент вам, вероятно, следует написать свою собственную оболочку assert.Другой вариант - поменять местами операнды и использовать оператор запятой. Вам нужны дополнительные круглые скобки, чтобы запятая не рассматривалась как разделитель между аргументами:
(это было скопировано из приведенных выше комментариев для лучшей видимости)
источник
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Вот моя версия макроса assert, который принимает сообщение и распечатывает все в понятной форме:
Теперь вы можете использовать это
А в случае сбоя вы получите такое сообщение:
Красиво и чисто, смело используйте его в своем коде =)
источник
x == y
. Затем Expr будет расширяться,if( !(x == y))
и здесь проверяется условие, а #Expr расширяется в строковый литерал"x == y"
, который мы затем помещаем в сообщение об ошибке.http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
Вы можете использовать это напрямую или скопировать код Boost. Также обратите внимание, что утверждение Boost - это только заголовок, поэтому вы можете просто получить этот единственный файл, если не хотите устанавливать все Boost.
источник
Поскольку ответ zneak несколько запутывает код, лучший подход - просто прокомментировать текст строки, о котором вы говорите. т.е. .:
Поскольку читатель ошибки assert все равно будет искать файл и строку из сообщения об ошибке, они увидят здесь полное объяснение.
Потому что, в конце концов, это:
читается лучше, чем это:
с точки зрения человеческого анализа кода, т.е. читаемость. Также не языковой взлом.
источник
assert - это комбинация макроса / функции. вы можете определить свой собственный макрос / функцию, используя
__FILE__
,__BASE_FILE__
и__LINE__
т. д., со своей собственной функцией, которая принимает настраиваемое сообщениеисточник
Для vc добавьте следующий код в assert.h,
источник