Является ли стандарт 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/С++ нет. Логическое значение является логическим, вы можете рассматривать целое число как логическое, но тот факт, что вывод является целым числом, ничего не говорит о том, что фактически выполняемая операция является поразмерной.