Является ли стандарт C явно обозначать значение истины как 0 или 1?
Мы знаем, что любые числа, не равные 0
, рассматриваются как true
в C, поэтому мы можем написать:
int a = 16;
while (a--)
printf("%d\n", a); // prints numbers from 15 to 0
Тем не менее, мне было интересно, определены ли true/false как 1
/0
в C, поэтому я пробовал код ниже:
printf("True = %d, False = %d\n", (0 == 0), (0 != 0)); // prints: True = 1, False = 0
В стандарте C явно указаны значения истинности true и false как 1
и 0
соответственно?
Ответы
Ответ 1
В стандарте C явно указаны значения истинности true
и false
как 0
и 1
соответственно?
Стандарт C определяет true
и false
как макросы в stdbool.h
, которые расширяются до 1
и 0
соответственно.
C11-§7.18:
Остальные три макроса подходят для использования в директивах #if
для предварительной обработки. Они
true
который расширяется до целочисленной константы 1
,
false
который расширяется до целочисленной константы 0
[...]
Относительно операторов ==
и !=
С11-§6.5.9/3:
Операторы ==
(равно) и !=
(не равные) аналогичны операторам связи, за исключением их более низкого приоритета. 108) Каждый из операторов дает 1
если указанное отношение истинно и 0
, если оно ложно. Результат имеет тип int
. Для любой пары операндов истинно одно из отношений.
Ответ 2
В C11 явно не указано. Все операции на уровне языка возвращают 1 как правдивые (и принимают любые ненулевые значения, включая NaN как истинные).
- Если вы беспокоитесь о
_Bool
, тогда true должен быть 1, потому что стандарт требует, чтобы он держал 0 и 1. (§6.2.5/2).
- Также в
<stdbool.h>
макрос true
расширяется до 1
(§7.18/3)
-
==
, !=
, <
, >
, <=
и >=
возвращает 0 или 1 (§6.5.8/6, §6.5.9/3).
-
!
, &&
и ||
возвращает 0 или 1 (§6.5.3.3/5, §6.5.13/3, §6.5.14/3)
-
defined
расширяется до 0 или 1 (§6.10.1/1)
Но все стандартные библиотечные функции, например. islower
просто сказать "отличное от нуля" для правды (например, §7.4.1/1, §7.17.5.1/3, §7.30.2.1/1, §7.30.2.2.1/4).
§6.2.5/2: объект, объявленный как тип _Bool
, достаточно велик, чтобы хранить значения 0 и 1.
§6.5.5.3/5. Результат оператора логического отрицания !
равен 0, если значение его операнда сравнивается с не равным 0, 1, если значение его операнда сравнивается с равным 0....
§6.5.8/6: каждый из операторов <
(меньше), >
(больше), <=
(меньше или равен) и >=
(больше или равно) должно давать 1, если указанное отношение истинно и 0, если оно ложно. 107)...
§6.5.9/3. Операторы ==
(равно) и !=
(не равные) аналогичны операторам связи, за исключением их более низкого приоритета .108) Каждый из операторов дает 1, если указанное отношение истинно и 0, если оно ложно....
§6.5.13/3: оператор &&
должен давать 1, если оба его операнда сравниваются не равными 0;...
§6.5.14/3: оператор ||
должен дать 1, если один из его операндов сравним неравномерно с 0;...
§6.10.1/1:... он может содержать унарные операторные выражения формы - defined identifier
- или - defined ( identifier )
- которые оцениваются до 1, если...
§7.4.1 (Функции классификации символов)/1: функции в этом подпункте возвращают ненулевые (истинные) тогда и только тогда, когда...
§7.18/3. Остальные три макроса подходят для использования в директивах #if
предварительной обработки. Они - true
- которые расширяются до целочисленной константы 1,...
§7.17.5.1/3: общая функция atomic_is_lock_free
возвращает ненулевое значение (true) тогда и только тогда, когда операции с объектами блокируются....
§7.30.2.1 (Функции классификации широкого символа)/1: функции в этом подпункте возвращают ненулевые (истинные) тогда и только тогда, когда...
§7.30.2.2.1/4: функция iswctype
возвращает ненулевое значение (true) тогда и только тогда, когда...
Ответ 3
Есть две области стандарта, о которых вам нужно знать при работе с булевыми значениями (под которыми я имею в виду значения true/false, а не тип C bool/_Bool
) в C.
Первое связано с результатом выражений и может быть найдено в различных частях C11 6.5 Expressions
(например, операторы отношения и равенства). Суть в том, что всякий раз, когда булево значение генерируется выражением, оно...
... дает 1, если указанное отношение истинно и 0, если оно ложно. Результат имеет тип int.
Итак, да, результат любого булево выражающего выражения будет равен true для true или нулю для false. Это соответствует тому, что вы найдете в stdbool.h
, где стандартные макросы true
и false
определяются одинаковым образом.
Имейте в виду, однако, что, следуя принципу надежности "быть консервативным в том, что вы отправляете, либеральным в том, что вы принимаете", интерпретация целых чисел в булевом контексте несколько более расслаблена.
Опять же, из различных частей 6.5
вы увидите такой язык, как:
Оператор ||
должен давать 1, если один из его операндов сравнивается не равным 0; в противном случае он дает 0. Результат имеет тип int.
Из этого (и других частей) видно, что ноль считается ложным, а любое другое значение истинно.
В стороне, язык, определяющий, какое значение используется для логического генерации и интерпретации, также появляется на C99 и C89, поэтому они уже довольно долгое время. Даже K & R (второе издание ANSI-C и первое издание) указали, что с текстовыми сегментами, такими как:
Реляционные выражения типа i > j
и логические выражения, связанные &&
и ||
, имеют значение 1
, если true, и 0
, если false.
В тестовой части if
, while
, for
и т.д. "истина" означает "ненулевое".
Оператор &&
... возвращает 1, если оба его операнда сравниваются не равными нулю, 0 в противном случае.
Оператор ||
... возвращает 1, если либо его операнды сравниваются не равными нулю, а 0 в противном случае.
Макросы в stdbool.h
также отображаются на C99, но не в C89 или K & R, поскольку этот файл заголовка не существовал в этой точке.
Ответ 4
Вы смешиваете множество разных вещей: управляющие операторы, операторы и логические типы. У каждого свои правила.
Операторы управления работают, например, как оператор if
, C11 6.4.8.1:
В обеих формах первое подзадача выполняется, если выражение сравнивается не равным 0.
while
, for
и т.д. имеют одно и то же правило. Это не имеет ничего общего с "истинным" или "ложным".
Как для операторов, которые предположительно приводят к логическому результату, они фактически дают int
со значением 1 или 0. Например, операторы равенства C11 6.5.9:
Каждый из операторов дает 1, если указанное отношение истинно и 0 если оно ложно
Все вышесказанное состоит в том, что C не имел булевского типа до 1999 года, и даже когда он его получил, приведенные выше правила не были изменены. Таким образом, в отличие от большинства других языков программирования, где операторы и операторы дают булевский тип (например, С++ и Java), они просто дают значение int
со значением 0 или не равным нулю. Например, sizeof(1==1)
даст 4 в C, но 1 в С++.
Фактический логический тип в C называется _Bool
и требует современного компилятора. Заголовок stdbool.h
определяет макросы bool
, true
и false
, которые расширяются до _Bool
, 1
и 0
соответственно (для совместимости с С++).
Однако считается хорошей практикой программирования для обработки управляющих операторов и операторов, как если бы они на самом деле требовали/приводили булевский тип. Некоторые стандарты кодирования, такие как MISRA-C, рекомендуют такую практику. То есть:
if(ptr == NULL)
вместо if(ptr)
.
if((data & mask) != 0)
вместо if(data & mask)
.
Цель такого стиля - повысить безопасность типов с помощью инструментов статического анализа, что, в свою очередь, уменьшает количество ошибок. Возможно, этот стиль имеет смысл только в том случае, если вы используете статические анализаторы. Хотя в некоторых случаях это приводит к более читабельному самодокументируемому коду, например
if(c == '\0')
Хорошо, цель понятна, код самодокументирован.
против
if(c)
Bad. Может означать что угодно, и мы должны искать тип c
, чтобы понять код. Является ли это целым числом, указателем или символом?
Ответ 5
Я программировал на многих языках. Я видел, что истинно 1 или -1 в зависимости от языка. Логика истинного существа 1 заключалась в том, что бит был либо 0, либо 1. Логика истинного существа -1 заключалась в том, что! оператор был одним дополнением. Он изменил все 1 на 0 и все 0 на 1 в int. Итак, для int,! 0 = -1 и! (- 1) = 0. Это сотрясало меня настолько, что я не сравниваю что-то, чтобы быть истинным, но вместо этого сравним его!= False. Таким образом, мой стиль программирования работает на всех языках. Поэтому я должен не беспокоиться об этом, но программа, чтобы ваш код работал правильно в любом случае.
Ответ 6
Это произошло из-за реляционных операторов в вашем выражении printf
.
Оператор ==
и оператор !=
Так как (0 == 0)
имеет значение true, оно дает значение 1
тогда как (0 != 0)
не имеет значения true, дает значение 0
.
Ответ 7
Этот ответ нужно посмотреть немного поближе.
Фактическое определение в С++ заключается в том, что все, что не является 0, рассматривается как истина. Почему это имеет значение? Потому что С++ не знает, что такое целое, по тому, как мы об этом думаем, - мы создаем этот смысл, все, что у него есть, - это оболочка и правила для того, что это значит. Он знает, что такое биты, то, что составляет целое число.
1 как целое число свободно представлено в битах, например, 8-битный подписанный int как 0000 0001. Много раз визуальное изображение - это немного ложь, -1 - гораздо более распространенный способ представить его из-за подписанный характер "целого". 1 действительно не может означать истину, почему? Потому что это НЕ операция 1111 1110. Это действительно серьезная проблема для логического. Когда мы говорим о логическом, это всего лишь 1 бит - это действительно просто, 0 - false, а 1 - true. Все логические операции выполняются как тривиальные. Вот почему '-1' следует обозначать как "истинный" для целых чисел (подписанный). 1111 1111 NOT'ed становится 0000 0000 --- логика держится, и мы хороши. Unsigned ints немного сложнее и гораздо чаще используется в прошлом - где 1 означает true, потому что легко предположить логику, что "ничего не равно 0".
Это объяснение. Я говорю, что принятый ответ здесь неверен - четкого определения в определении C/С++ нет. Логическое значение является логическим, вы можете рассматривать целое число как логическое, но тот факт, что вывод является целым числом, ничего не говорит о том, что фактически выполняемая операция является поразмерной.