Подтвердить что ты не робот

Кастинг int для bool в C/С++

Я знаю, что в C и С++ при передаче bools в ints (int)true == 1 и (int)false == 0. Мне интересно, кастинг в обратном направлении...

В приведенном ниже коде все следующие утверждения сохраняются для меня в файлах .c, скомпилированных с Visual Studio 2013 и Keil μVision 5. Обратите внимание на (bool)2 == true.

Что говорят стандарты C и С++ о том, чтобы отличать ненулевые целые числа, отличные от нуля, для bools? Указано ли это поведение? Пожалуйста, включите цитаты.

#include <stdbool.h>
#include <assert.h>

void TestBoolCast(void)
{
    int i0 = 0, i1 = 1, i2 = 2;

    assert((bool)i0 == false);
    assert((bool)i1 == true);
    assert((bool)i2 == true);

    assert(!!i0 == false);
    assert(!!i1 == true);
    assert(!!i2 == true);
}

Не дубликат Можно ли считать (bool) true == (int) 1 для любого компилятора С++?:

  • Литье в обратном направлении (int → bool).
  • Нет обсуждения ненулевых значений, отличных от одного.
4b9b3361

Ответ 1

0 значения базовых типов (1) (2) отображаются на false.

Другие значения соответствуют true.

Это соглашение было установлено в оригинале C через его операторы управления потоком; В то время C не имел логического типа.


Общей ошибкой считается, что в качестве возвращаемых значений функции false указывает на сбой. Но, в частности, из main it false, что указывает на успех. Я видел, как это делалось неправильно много раз, в том числе в стартовом коде Windows для языка D (когда у вас есть такие люди, как Уолтер Брайт и Андрей Александреску, ошибаются, тогда это просто помогает ошибиться), поэтому этот хэдз-ап будьте осторожны.


Нет необходимости использовать для bool для встроенных типов, потому что это преобразование неявно. Однако Visual С++ (компилятор Microsoft С++) имеет тенденцию выпускать предупреждение о производительности (!) Для этого, чистое глупое предупреждение. Маскирования недостаточно, чтобы закрыть его, но преобразование посредством двойного отрицания, т.е. return !!x, прекрасно работает. Можно читать !! как "преобразовать в bool", так как --> можно читать как "идет". Для тех, кто глубоко в удобочитаемости обозначений оператора.; -)


1) С++ 14 §4.12/1 "Значение нулевого значения, нулевого указателя или значение указателя нулевого элемента преобразуется в false, любое другое значение преобразуется в true. -инициализация (8.5), prvalue типа std::nullptr_t может быть преобразована в prvalue типа bool, результирующее значение false."
2) C99 и C11 §6.3.1.2/1 "Когда любое скалярное значение преобразуется в _Bool, результат равен 0, если значение сравнивается с 0, в противном случае результат равен 1."

Ответ 2

Далее приведен стандарт C11 (окончательный вариант).

6.3.1.2: Когда любое скалярное значение преобразуется в _Bool, результат равен 0, если значение сравнивается равный 0; в противном случае результат равен 1.

bool (отображаемый stdbool.h во внутреннее имя _Bool для C) сам по себе беззнаковый целочисленный тип:

... Тип _Bool и беззнаковые целочисленные типы, которые соответствуют стандартным типам со знаком целочисленного типа, являются стандартными целыми типами без знака.

Согласно 6.2.5p2:

Объект, объявленный как тип _Bool, достаточно велик, чтобы хранить значения 0 и 1.

AFAIK эти определения семантически идентичны С++ - с незначительной разницей встроенных (!) имен. bool для С++ и _Bool для C.

Обратите внимание, что C не использует термин rvalues ​​, как это делает С++. Однако в C указатели являются скалярами, поэтому назначение указателя на _Bool ведет себя как в С++.

Ответ 3

Другой способ удалить предупреждения (по крайней мере, в MS Visual Studio 2019 C++) - это использовать троичный оператор и установить значение, равное true или false:

int i = 3; // Or another value
bool b = (i ? true : false);

Или чтобы было понятнее:

int i = 3; // Or another value
bool b = (i == 0 ? false : true);