Мы знаем, что любые числа, которые не равны 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 явно указывает значения истинности истинного и ложного как 1
и 0
соответственно?
gcc
с помощью,-std=c89
и это дает тот же результат.Ответы:
Стандарт C определяет
true
иfalse
как макросы, вstdbool.h
которых расширяются до1
и0
соответственно.C11-§7.18:
Для операторов
==
и!=
стандарт говоритC11-§6.5.9 / 3:
источник
0 == 0
и0 != 0
прочее, а не в значении макросов.true
он имел в виду «ценность истинного сравнения» или что-то в этом роде, а не макросtrue
ctrl
f
NaN == NaN
ложно иNaN != NaN
верно. С этим утверждением проблем нет.Это явно не указано в 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).источник
Есть две области стандарта, о которых вам нужно знать при работе с логическими значениями (под которыми я подразумеваю истинные / ложные значения, а не конкретный
bool/_Bool
тип C ) в C.Первый связан с результатом выражений и может быть найден в различных частях
C11 6.5 Expressions
(например, операторов отношения и равенства). Суть в том, что всякий раз, когда логическое значение генерируется выражением, оно ...Итак, да, результатом любого выражения, генерирующего логическое значение, будет единица для истины или ноль для ложи. Это соответствует тому, что вы найдете в
stdbool.h
стандартных макросах,true
иfalse
они определены таким же образом.Однако имейте в виду, что, следуя принципу устойчивости «будь консервативным в том, что вы отправляете, либеральным в том, что вы принимаете», интерпретация целых чисел в логическом контексте несколько более расслаблена.
Опять же, из разных частей
6.5
вы увидите такие выражения, как:Из этого (и других частей) очевидно, что ноль считается ложным, а любое другое значение - истинным.
Кроме того, язык, определяющий, какое значение используется для генерации и интерпретации логических значений, также появился в C99 и C89, так что они существуют уже довольно давно. Даже K&R (второе издание и первое издание ANSI-C ) уточняет это с помощью таких текстовых сегментов, как:
Макросы также
stdbool.h
появляются в C99, но не в C89 или K&R, поскольку этот файл заголовка в тот момент не существовал.источник
||
,==
и!=
т. д. yieldint
, не является логическим типомif
,while
,for
и т.д.,„правда“просто означает„не нуль“.» Это основная часть ответа, и, на мой взгляд, это неудачный выбор Денниса Ричи давным-давно. Любой, кто написал функции, которые обычно возвращают коды ошибок в качестве возвращаемого значения#define noErr 0
и любой ненулевой код ошибки, является ошибкой. И тут проблема в простоте и красотеif ( ready_to_do_something() ){do_something();}
не работает. Это должно быть:if ( !not_ready_to_do_something() ){do_something();}
«Есть много лжи, но только одна правда». ИСТИНА должно быть 0.A.7.6/7/10/11
(реляционное / равенство / логическое и / логическое или) все указывают, что в результате он дает 0 или 1. Обновили ответ, чтобы включить это.Вы смешиваете много разных вещей: управляющие операторы, операторы и логические типы. У каждого свои правила.
Управляющие операторы работают как, например,
if
оператор C11 6.4.8.1:while
иfor
т. д. имеют то же правило. Это не имеет ничего общего с «истинным» или «ложным».Что касается операторов, которые предположительно дают логический результат, на самом деле они дают
int
значение 1 или 0. Например, операторы равенства, C11 6.5.9:Все вышесказанное объясняется тем, что в C не было логического типа до 1999 года, и даже когда он его получил, вышеуказанные правила не изменились. Таким образом, в отличие от большинства других языков программирования, где операторы и операторы выдают логический тип (например, C ++ и Java), они просто возвращают
int
значение с нулевым или ненулевым значением. Например,sizeof(1==1)
в C будет 4, а в C ++ - 1.Фактический логический тип в C назван
_Bool
и требует современного компилятора. Заголовокstdbool.h
определяет макросыbool
,true
иfalse
, которые расширяются до_Bool
,1
и0
соответственно (для совместимости с C ++).Однако считается хорошей практикой программирования рассматривать управляющие операторы и операторы, как если бы они действительно требовали / давали логический тип. Некоторые стандарты кодирования, такие как MISRA-C, рекомендуют такую практику. То есть:
if(ptr == NULL)
вместоif(ptr)
.if((data & mask) != 0)
вместоif(data & mask)
.Цель такого стиля - повысить безопасность типов с помощью инструментов статического анализа, что, в свою очередь, уменьшает количество ошибок. Возможно, этот стиль имеет смысл только при использовании статических анализаторов. Хотя в некоторых случаях это приводит к более читаемому, самодокументирующемуся коду, например
if(c == '\0')
Хорошо, замысел ясен, код самодокументируется.
против
if(c)
Плохой. Может означать что угодно, и нам нужно искать тип,
c
чтобы понять код. Это целое число, указатель или символ?источник
sizeof(bool)
зависит от реализации в C ++. См. Stackoverflow.com/questions/4897844/is-sizeofbool-defined .if(ptr != NULL)
или возможноif(!ptr)
?if(c == '\0')
поддается особенно распространенной ошибке программирования для начинающихif(c = '\0')
, поэтому я ее избегаю. Согласен,if(c)
плохо ... так и должно быть, например,if(valveIsOpen)
Я программировал на многих языках. Я видел true равным 1 или -1 в зависимости от языка. Логика, лежащая в основе истинного значения 1, заключалась в том, что бит был либо 0, либо 1. Логика, лежащая в основе истинного значения -1, заключалась в том, что! оператор был дополнением. Он изменил все 1 на 0 и все 0 на 1 в int. Итак, для int! 0 = -1 и! (- 1) = 0. Это меня настолько сбило с толку, что я не сравниваю что-то как == true, а вместо этого сравниваю это как! = False. Таким образом, мой стиль программирования работает на всех языках. Поэтому мой ответ - не беспокоиться об этом, а программировать так, чтобы ваш код работал правильно в любом случае.
источник
Этот ответ требует более внимательного изучения.
Фактическое определение в C ++ заключается в том, что все, кроме 0, считается истиной. Почему это актуально? Поскольку C ++ не знает, что такое целое число, по тому, как мы о нем думаем - мы создаем это значение, все, что он содержит, - это оболочка и правила того, что это означает. Однако он знает, что такое биты, составляющие целое число.
1 как целое число свободно представлено в битах, скажем, 8-битное целое число со знаком как 0000 0001. Часто то, что мы видим визуально, немного ложь, -1 - гораздо более распространенный способ представления этого из-за характера знака. целого числа. Я действительно не могу иметь в виду истинное собственное, почему? Поскольку это НЕ операция, это 1111 1110. Это действительно серьезная проблема для логического значения. Когда мы говорим о логическом, это всего лишь 1 бит - это действительно просто, 0 - ложь, а 1 - истина. Все логические операции просты. Вот почему «-1» следует обозначать как «истина» для целых чисел (со знаком). 1111 1111 NOT превращается в 0000 0000 --- логика верна, и все в порядке. Беззнаковые целые числа - это немного сложно, и в прошлом они использовались гораздо чаще - где 1 означает истину, потому что легко подразумевать логику, которая '
Вот и объяснение. Я говорю, что принятый здесь ответ неверен - в определении C / C ++ нет четкого определения. Логическое значение - это логическое значение, вы можете рассматривать целое число как логическое, но тот факт, что результат является целым числом, ничего не говорит о фактически выполняемой операции, является побитовым.
источник
Это произошло из-за операторов отношения в вашем
printf
утверждении.Оператор
==
и оператор!=
Поскольку
(0 == 0)
верно так, он дает значение1
тогда как,
(0 != 0)
это не так, дает значение0
.источник