При оценке целых чисел как булевых в C/С++ отрицательные числа истинны или ложны? Всегда ли они истинны/ложны независимо от компиляторов?
Не отрицательные числа возвращают false в C/С++?
Ответ 1
Все ненулевые значения будут преобразованы в true
и нулевые значения до false
. При отрицательных числах, отличных от нуля, они преобразуются в true
.
Цитата из стандарта С++ 11 (акцент мой):
4.12 Логические преобразования [conv.bool]
1 Значение арифметики, неперечисленное перечисление, указатель или указатель тип члена может быть преобразован в prvalue типа bool. Ноль значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется до
false
; любое другое значение преобразуется вtrue
.. Значение типа std:: nullptr_t может быть преобразован в prvalue типа bool; итоговое значение false.
Всегда ли они истинны/ложны независимо от компиляторов?
Вы получите только вышеуказанную гарантию, когда ваш компилятор соответствует стандартам или, по крайней мере, соответствует этой конкретной части стандарта. На практике все компиляторы имеют это стандартное поведение, поэтому беспокоиться не о чем.
Ответ 2
Вы можете проверить это самостоятельно, скомпилировав это:
#include <stdio.h>
int main(int argc, char** argv) {
if (-1) {
printf("-1 is true\n");
} else {
printf("-1 is false\n");
}
return 0;
}
Результаты:
$ gcc -Wall -pedantic test.c -o test-c
$ g++ -Wall -pedantic test.c -o test-cpp
$./test-c
-1 is true
$./test-cpp
-1 is true
Конечно, чтобы ответить на вторую часть вашего вопроса: "Всегда ли они верны/неверны независимо от компиляторов?", Единственный способ быть полностью уверенным - взглянуть на спецификацию. В целом, однако, компиляторы предупреждают вас, если вы делаете что-то опасное, и вы можете видеть из вышеприведенного вывода, что даже с "педантичными" предупреждениями, gcc
считает этот код идеальным.
Ответ 3
Краткий ответ. Отрицательные значения и любые ненулевые значения в целом рассматриваются как истинные при использовании в качестве условий.
Для C существует ряд контекстов, в которых выражение рассматривается как условие. Условия не обязательно относятся к типу bool
или _Bool
; этот тип был добавлен к языку только по стандарту 1999 года.
Наиболее очевидным из этих контекстов является выражение в выражении if
, но есть и другие примеры: while
, do-while
, второе выражение в заголовке for
, первый операнд условного оператора ?:
и операнд операторов !
, &&
и ||
. (Я думаю, что это исчерпывающий список, но я не уверен.)
Вот что говорит стандарт C о поведении оператора if
("две формы" относятся к if
с предложением else
и без него):
В обеих формах первая подстановка выполняется, если выражение не равно 0.
Что означает, что это:
if (foo) ...
эквивалентно этому:
if ((foo) != 0) ...
(добавление дополнительных скобок, чтобы избежать проблем с приоритетом операторов). Смысл понятен, если foo
имеет тип int
. Если foo
имеет некоторый тип с плавающей точкой, 0
преобразуется в тот же тип (что может вызвать некоторые тонкости, если значение оказывается отрицательным нулем или NaN). И если foo
является указателем, 0
обрабатывается как константа нулевого указателя; if (ptr)
эквивалентен if (ptr != NULL)
(при условии, что определение NULL
является видимым).
Для C++ правила сформулированы немного по-другому, но эффект тот же. Условие в операторе C++ if
преобразуется в тип bool
(в отличие от C, тип bool
был встроен в C++ с момента его ранней истории). Преобразование значения любого скалярного типа в bool
определяется стандартом C++ как:
Нулевое значение, нулевое значение указателя или нулевое значение указателя элемента преобразовано в ложное; любое другое значение преобразуется в true. prvalue типа std::nullptr_t может быть преобразовано в prvalue из введите bool; результирующее значение ложно.
Таким образом, как в C, так и в C++ любое скалярное значение (т.е. целое число, число с плавающей запятой или указатель) может использоваться как условие, и условие ложно, если скаляр равен нулю, и истинно, если оно не равно в ноль. C определяет это как сравнение неравенства с 0
; C++ определяет его как преобразование в bool
- но результат тот же.
Это немного выходит за рамки вопроса, но я упомяну, что важно отметить, что значение, которое рассматривается как истинное условие, не обязательно равно true
. true
(то есть 1
в C, если у вас есть #include <stdbool.h>
и уникальное значение типа bool
в C++) - это лишь одно из многих значений, которые обладают "истинностью" при использовании в условии. Вот почему вы почти никогда не должны писать:
if (cond == true) ...
либо в C, либо в C++ (если вам действительно не нужно сравнивать его с этим одним значением); просто напишите:
if (cond) ...
Пример C++:
#include <iostream>
int main() {
int n = 2;
if (n) std::cout << "n has truthiness\n";
else std::cout << "n does not have truthiness\n";
if (n == true) std::cout << "n == true\n";
else std::cout << "n != true\n";
}
Вывод:
n has truthiness
n != true
Ответ 4
Все, что не является 0
, будет преобразовано в true
(1 в случае C). Значение zero
будет преобразовано в false
(0 в случае C). Что касается C, если мы посмотрим на черновик проекта C99 6.3.1.2
Логический тип параграфа 1 гласит:
Когда любое скалярное значение преобразуется в _Bool, результат равен 0, если значение сравнивается с равным до 0; в противном случае результат равен 1.
Для полноты, если мы посмотрим на раздел 7.16
Логический тип и значения, приведенные в параграфе 2, говорят:
The macro
bool
expands to _Bool.
относительно С++ черновик стандарта С++ в разделе 4.12
Логические преобразования в абзаце 1 говорят (выделено мной):
Значение арифметики, неперечисленное перечисление, указатель или указатель на тип члена может быть преобразовано в prvalue типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в значение true. [...]
Это должно выполняться независимо от того, какой компилятор вы используете.
Ответ 5
Хороший вопрос. Ответ "зависит".if (-1) { // this is always true
}
С другой стороны, предположим, что вы на 16-битной машине:
if (-65536) { // this is always false
}
С другой стороны,
int a = whatever doesn't matter;
if (a < 0) { // this might or might not be true
if (a) { // this will always be true if we get here
}
}
Таким образом, отрицательные числа не всегда являются ложными, кроме случаев, когда они всегда есть.