кастинг 0, чтобы аннулировать - PullRequest
11 голосов
/ 10 августа 2011

В моей реализации C ++ (реализация Visual Studio 2008) я вижу следующую строку в <cassert>

#ifdef  NDEBUG
#define assert(_Expression) ((void)0)

Я не понимаю необходимости приводить 0 к void.Мне кажется, что

#ifdef  NDEBUG
#define assert(_Expression) (0)

или даже просто

#ifdef  NDEBUG
#define assert(_Expression) 0

подойдет, учитывая контекст, в котором можно использовать assert(expr).опасность 0 типа int вместо 0 типа void в этом случае?Любые реалистичные примеры?

1 Ответ

22 голосов
/ 10 августа 2011

Единственная цель сложного выражения (void)0 - избегать предупреждений компилятора. Если у вас просто было голое, бесполезное выражение, компилятор может предупредить о выражении, которое не имеет никакого эффекта. Но, явно приведя что-то к void, вы указываете, что хотите это сделать.

(Подумайте о том, как запуталось бы это, если бы компилятор вдруг сказал: «Предупреждение: выражение 0; не имеет никакого эффекта.», Когда все, что вы сделали, переключилось в режим выпуска.)

Это было также обычной практикой в ​​C, где вы сказали бы (void)printf("Hello");, чтобы сообщить компилятору, что вы намеренно решили игнорировать возвращаемое значение функции.

Приведение (void) - это не просто выбор конкретной реализацией; это требуется по стандарту C. Цитируя стандарт ISO C 2011 года (аналогичная формулировка появляется в изданиях 1990 и 1999 годов):

Если NDEBUG определено как имя макроса в точке исходного файла где <assert.h> включен, макрос assert определяется просто как

#define assert(ignore) ((void)0)

Стандарт C ++ требует, чтобы содержимое заголовка <cassert> совпадало с заголовком Standard C <assert.h>.

...