Форум » C/C++ » Что за зверь такой - оператор !! » Ответить

Что за зверь такой - оператор !!

Сыроежка: Забавный вопрос встретил на одном форуме. Участник форума спрашивал, что означает оператор !!, является ли он стандартным оператором языков С/С++, или это расширение конкретного компилятора. Этот вопрос - пример того, что можно так заработаться, что когда встречается простая, но неиспользуемая никогда в собственной практике программиста конструкция, то программист может растеряться от неожиданности. Естественно никакого нового оператора !! в С/С++ не существует. Это конструкция представляет собой последовательное применение дважды стандартного оператора отрицания !. Почему же вызывает удивление ее наличие в коде? Дело в том, что не сразу понятен смысл ее использования, то есть а зачем это делается? Ззачем два раза подряд применяется операция отрицания? На самом деле этот прием распространен в языке С времен стандарта С89, где отсутсвует булевый тип. Иногда требуется для значений выражений, отличных от нуля, сопоставить значение равное 1. То есть имитируется с помощью числа целого типа булевый тип, принимающий только два значения: 0 и 1. Допустим, мы ввели определение такого булева типа. Это можно сделать по разному. Либо с помощью typedef , как, например, typedef int bool_t; Либо с помощью перечисления: typedef enum { false, true } bool_t; Однако возникает вопрос, а как сделать так, чтобы переменная нововведенного типа получала только значения равные 0 и 1? То есть допутсим мы объявили [pre2]typedef int bool_t; bool_t bFlag; int x = 10;[/pre2] И хотим переменной bFlag присвоить значение либо 0, либо 1 в зависимости от того, отлично ли от нуля значение переменной x. Как это проще сделать? Можно было бы написать [pre2]bFlag = ( x ) ? 1 : 0;[/pre2] Но это довольно вычурная конструкция. Проще же на самом деле написать [pre2]bFlag = !!x;[/pre2] Дело в том, что соогласно стандарту С значением операции отрицания является точно одно из двух значений: либо 0, либо 1. Поэтому когда мы первый раз применили отрицание ! к x, мы получили 0, а второе применение операции отрицания ! даст нам то, что нужно, то есть в данном конкретном случае 1. Поэтому применение последовательно двух отрицаний !! к выражению, позволяет получить либо 1, если выражение отлично от 0, либо 0, если выражение равно 0, то есть смоделировать область значений для булева типа.

Ответов - 3

Сыроежка: Хотел бы добавить, что в С99 нет необходимости в использовании двойного оператора отрицания для преобразования любого выражения к целочисленному значению 0 или 1, так как в С99 введен булевой тип _Bool . На самом деле _Bool - это целочисленный беззнаковый тип, который принимает два значения 0 и 1. Любое выражение, присваиваемое переменной этого типа, преобразуется в 1, если значение выражения, стоящего справа от оператора присваивания, отлично от 0. Поэтому вместо трюка с !! в следующем примере, который уже демонстрировался выше [pre2]typedef int bool_t; bool_t bFlag; int x = 10; bFlag = !!x;[/pre2] в С99 можно записать проще [pre2] _Bool bFlag; int x = 10; bFlag = x;[/pre2]

PSP: Сыроежка пишет: в С99 можно записать проще А в новом стандарте тип _Bool исключен?

Сыроежка: PSP пишет: А в новом стандарте тип _Bool исключен? Тип _Bool был введен в язык С в 1999 году. Этот стандарт является текущим стандартом языка С. Хотя если следовать информации с официального сайта рабочей группы ISO/IEC, уже опубликована новая версия этого стандарта ( New revision of ISO/IEC 9899:2011 C standard (C11) published). В С99 тип _Bool определяется как стандартный беззнаковый целочисленный тип наряду с unsigned char, unsigned short, unsigned int, unsigned long и unsigned long long. Про тип _Bool говорится, что он должен быть достаточно велик, чтобы хранить значения 0 и 1. То есть на самом деле размер типа _Bool оставлен на усмотрение разработчиков компиляторов. В С++ имеется тип bool, которые принимает два значения false и true. И хотя в С++ тип bool также относится к целочисленным типам, _Bool и bool - это два различных типа. То есть в С++ нет ключевого слова _Bool , а в С нет ключевого слова bool. В программах на С99 можно подключить заголовочный файл <stdbool.h>, где определяются макросы bool, true и false, которые позволяют ввести алиасы для типа _Bool и его значений 0 и 1 в стиле С++. Замечу, что компилятор MS VC++ 2010 до сох пор не поддерживает стандарт С99 для языка С. То есть он может компилировать программы, написанные лишьь на С89.




полная версия страницы