Nano Hash - криптовалюты, майнинг, программирование

Использование true и false в C

Насколько я понимаю, есть 3 способа использовать логические значения в c

  1. с типом bool, затем с использованием true и false
  2. определение с помощью препроцессора #define FALSE 0 ... #define TRUE !(FALSE)
  3. Просто чтобы использовать константы напрямую, то есть 1 и 0

есть ли другие методы, которые я пропустил? Каковы плюсы и минусы разных методов?

Я полагаю, что самым быстрым будет номер 3, 2 еще легче читается (хотя побитовое отрицание немного увеличивает накладные расходы), 1 наиболее читаем, не совместим со всеми компиляторами.

12.02.2010

  • Вы действительно думаете, что компиляторы будут ждать, пока время выполнения не изменит константу? 12.02.2010
  • Чтобы продолжить, чтобы я не выглядел придурком, ни один компилятор на самом деле не тратит время на это. Компиляторы - это тяжелые оптимизаторы, и если он знает, что результаты всегда будут одинаковыми, он вставит это вместо этого. Он никогда не будет ждать, пока среда выполнения оценит int i = 12 + 3 * 4;; он просто скажет int i = 24;. Беспокойство о производительности - это обычная проблема, не расстраивайтесь. Оптимизация идет последней, и когда она все-таки приходит, вам нужно рассчитать время своего кода и посмотреть на вывод сборки, а не гадать. Даже если бы это стоило цикла, я бы выбрал наиболее удобочитаемое решение. Только когда это оказалось 12.02.2010
  • Я бы переключился на более быстрое решение, рассчитав их, чтобы убедиться, что они действительно быстрее. Когда предоставляется выбор между удобочитаемостью и циклом, выберите удобочитаемость. :) Легко сделать хороший код быстрым, но сложно сделать хороший быстрый код. 12.02.2010
  • При использовании макросов помните, что (x == TRUE) не то же самое, что (x). Первое верно, только если x содержит значение TRUE. Последнее верно для любого ненулевого значения. 12.02.2010
  • +1 @Devon, большую часть времени я использую только константы как возвращаемые значения. 12.02.2010
  • Я не рекомендую определять специальные логические макросы; это только соблазняет начинающих программистов писать такие вещи, как if(foo == TRUE) или if(foo == FALSE), что является злодеянием для большинства языков, но тем более для C, где любое скалярное значение != 0 считается истинным в логических контекстах; по аналогичным, но менее серьезным причинам мне не нравятся if(foo != NULL) и if(foo == NULL) указатели; поскольку это не может привести к появлению ошибок в сравнении с TRUE, это просто дело вкуса, но использование if(foo) и if(!foo) для любого скалярного значения, я думаю, больше соответствует внешнему виду языка C. 12.02.2010
  • stackoverflow.com/questions/1921539/using-boolean-values -в-с 12.02.2010
  • что лучше ... всегда * субъективно и слишком легко аргументировано, чтобы рисковать. Я отредактировал текст вопроса, чтобы помочь, но даже это небезопасно. Наконец-то я с Джеймслином ... 14.02.2010
  • @GManNickG на самом деле, я ожидал, что компиляторы упустят это, когда константа используется через границы единицы компиляции (в другом файле C). Оптимизация потребует оптимизации кода после связывания, поскольку значение не может быть известно во время компиляции текущего модуля компиляции (до связывания). Есть идеи, как компиляторы избегают этого? 21.08.2014
  • Ммм ... Я не специалист по C, но разве !(FALSE) логическое отрицание? В противном случае, если бы ! был побитовым, он бы оценил как -1, нет? 29.04.2016

Ответы:


1

Просто включите <stdbool.h>, если это предусмотрено вашей системой. Это определяет ряд макросов, включая bool, false и true (определены как _Bool, 0 и 1 соответственно). См. Раздел 7.16 C99 для более подробной информации.

12.02.2010
  • Bool не является макросом. Тип - _Bool. В противном случае это ужасно сломало бы старый код. 12.02.2010
  • Вы можете использовать _Bool, не включая stdbool.h 12.02.2010

  • 2

    Просто используйте 0 или 1 прямо в коде.

    Для программистов на C это так же интуитивно понятно, как истина или ложь.

    12.02.2010
  • Для программистов на C также верно значение -1, поскольку оно не равно нулю. В этом отношении 42 и -234 также являются истинными значениями. Я видел -1, -2 и другие значения как истинные. Некоторые функции возвращают 0 (ноль) как успешные. Хммм, хватит для последовательности. 12.02.2010
  • Обычно я вижу, что 1 или -1 используются как истинные значения. -1, потому что это все единицы в двоичном формате. Я хотел бы знать, где вы нашли -2. 12.02.2010
  • Я согласен с Томасом. Тот факт, что 0 используется как код ошибки для отсутствия ошибки (а часто также как тип int), иногда делает неочевидным, должно ли значение использоваться в логическом контексте. 12.02.2010
  • Подумайте о функции, возвращающей 0 в случае отсутствия ошибок, как о том, возникли ли у вас какие-либо проблемы при ответе на вопрос? - 0 = ложь = нет. int fail = close(fd); if (!fail) { great(); } else { weep(); } 14.02.2010
  • @squelart: проблема в том, что многие функции, возвращающие логические значения, не имеют этой семантики и возвращают истинное значение в случае успеха и ложное в случае неудачи. (Например, большая часть Win32 API разработана таким образом.) 16.02.2010
  • Вы правы, разные схемы возврата сбивают с толку. Но если первоначальный разработчик использовал указанное выше предложение при первом использовании функции (в этот момент разработчик уже будет знать или читать о возвращаемом значении), то обслуживание, надеюсь, будет проще позже ... 16.02.2010
  • Шаблон возврата 0 для обозначения успеха является частью более крупного шаблона, а именно: функция возвращает положительное целочисленное значение (например, количество обработанных байтов или прошедшее время и т. Д.) В случае успеха. Ошибка указывается возвращением отрицательного целого числа. Если мы теперь применим этот шаблон к функции, которая возвращает только успех или неудачу, у нас останется -1 для неудачи и 0 для успеха. Многие системные вызовы и библиотечные функции Linux / Unix следуют этому шаблону, поэтому хорошо с ним ознакомиться. 05.01.2016
  • Некоторые значения не так верны, поскольку if (0.4) и if (abs(0.4)) различаются. 17.08.2018
  • Я иногда так делаю: Положительный: Истина / Коды успеха 0: Неопределенный / Неинициализированный Отрицательный: Ложь / Коды сбоя 16.04.2020

  • 3

    Обычно я делаю:

    typedef enum {FALSE = 0, TRUE} boolean;
    
    12.02.2010
  • почему вы явно устанавливаете FALSE = 0? Разве первый элемент перечисления автоматически не равен 0? 14.08.2011
  • @lindelof Просто на случай, если они добавят FileNotFound перед этим перечислением. ;-) 14.02.2013
  • @lindelof В этом есть смысл. Единственная важная вещь - убедиться, что FALSE равно 0. ИСТИНА может быть любым, если она отличается. 20.04.2019

  • 4

    При использовании типа bool, определенного в stdbool.h, проблемы возникают, когда вам нужно перенести код из более нового компилятора, поддерживающего тип bool, в более старый компилятор. Это могло произойти во встроенной среде программирования, когда вы переходите на новую архитектуру с компилятором C, основанным на более старой версии спецификации.

    Подводя итог, я бы придерживался макросов, когда важна переносимость. В противном случае делайте то, что рекомендуют другие, и используйте бюлит в типе.

    12.02.2010

    5

    Вы можете проверить, определен ли bool в c99 stdbool.h с помощью

    #ifndef __bool_true_false_are_defined || __bool_true_false_are_defined == 0
    //typedef or define here
    #endif
    
    12.02.2010
  • Извините за мой последний комментарий, мой поиск в PDF-файлах не работает. См. Раздел 7.16 для получения дополнительной информации о __bool_true_false_are_defined. 12.02.2010

  • 6

    Я бы пошел на 1. Несовместимости с ним не встречал, это естественнее. Но я думаю, что это часть C ++, а не стандарта C. Я думаю, что с грязным взломом с определениями или вашим третьим вариантом - не будет никакой производительности, а только боль при поддержании кода.

    12.02.2010
  • bool является частью C ++, но _Bool (с bool в качестве псевдонима) теперь является частью C (начиная с C99). 12.02.2010
  • Приятно знать, что. Спасибо. :) 12.02.2010
  • Я бы не стал выбирать 1, так как любое ненулевое значение верно. Таким образом, для значений со знаком -1 также верно. 12.02.2010
  • Я имею в виду вариант 1 ... с типом bool 12.02.2010

  • 7

    Я предпочитаю (1), когда я определяю переменную, но в выражениях, которые я никогда не сравниваю с true и false, просто беру неявное определение C if (flag) или if (! Flag) или if (ptr). Это способ C делать вещи.

    12.02.2010

    8

    Любое int кроме нуля истинно; false равно нулю. Таким образом, подобный код продолжает работать, как ожидалось:

    int done = 0;   // `int` could be `bool` just as well
    
    while (!done)
    {
         // ...
         done = OS_SUCCESS_CODE == some_system_call ();
    }
    

    IMO, bool - это переоцененный тип, возможно, перенесенный с других языков. int отлично работает как логический тип.

    12.02.2010
  • Переоценено: в C ++ bool - это отдельный тип, поэтому он может участвовать в перегрузке функций по той же причине, по которой символьные константы имеют тип char в C ++. Конечно, это не относится к C, в котором нет перегрузки функций. 12.02.2010
  • Нет, C нарушен тем, что не делает различий между логическими и целыми числами. 12.02.2010
  • C почти не сломан. Целое число - это набор логических значений, которыми можно управлять параллельно. Оценка набора в целом - это их значение, объединенное с помощью ИЛИ. 12.02.2010
  • @starblue: C99 представил специальный логический тип; если это упростит вам разум, вы можете притвориться, что C автоматически преобразует скалярные значения в _Bool в логических контекстах, что также есть во многих динамических языках. 12.02.2010
  • В _Bool хорошо то, что он позволяет компилятору сохранять его любым удобным способом (байт, слово, бит и т. Д.); возможно, даже дать вам возможность определить его размер во время компиляции (например, в некоторых компиляторах, где вы можете указать int как 2 или 4 байта или long как 4 или 8 байтов). У вас есть процессор, который хочет обращаться к вещам как к словам? Сделайте _Bool размер слова. Ваш процессор обращается к байтам так же легко, как и к словам? Сделайте это байтом, чтобы сэкономить место. Есть инструкции по битовому доступу? Может быть, а может и нет. Продолжая давнюю традицию C не прибегать к int размерам ... 12.02.2010
  • Я могу жить с тем, как работает C, но я думаю, что было ошибкой дизайна не разделить чисто логические и целочисленные типы. C ++ пытается исправить это, но ему мешает необходимость обратной совместимости с C. То, что такая же ошибка совершается в других языках, не делает его лучше. 12.02.2010
  • @starblue Не назвал бы это ошибкой. Это имело смысл в 70-х гг. 20.04.2019

  • 9

    Раньше я использовал #define, потому что они упрощают чтение кода, и не должно быть ухудшения производительности по сравнению с использованием чисел (0,1), потому что препроцессор преобразует #define в числа перед компиляцией. После запуска приложения препроцессор больше не мешает, потому что код уже скомпилирован.

    Кстати, это должно быть:

    #define FALSE 0 
    #define TRUE 1
    

    и помните, что -1, -2, ... 2, 3 и т. д. все оцениваются как истинные.

    12.02.2010
  • ИСТИНА - это значение только для записи - при чтении / сравнении и т. Д. Любое ненулевое значение должно рассматриваться как истинное. 12.02.2010
  • по какой-то причине TRUE обычно определяется как #define TRUE! (FALSE) 12.02.2010
  • @Tom - это потому, что !1 возвращает 0, но !0 возвращает истинное значение, которое может быть самым разнообразным числом. #define TRUE !(FALSE) гарантирует, что TRUE == !0 независимо от того, какое точное значение возвращает !0. 12.02.2010

  • 10

    Я не знаю вашей конкретной ситуации. Когда я писал программы на C, мы всегда использовали №2.

    #define FALSE = 0
    #define TRUE = !FALSE
    

    В противном случае это могло быть на чужой платформе для DOS или процессоров на базе Intel. Но раньше я использовал и C, и ASM вместе, создавая графические библиотеки и графическую IDE. Я был настоящим поклонником Майкла Абраша и намеревался узнать о наложении текстур и так далее. Так или иначе! Вопрос не в этом!

    Это была наиболее часто используемая форма для определения логических значений в C, так как этот заголовочный файл stdbool.h тогда еще не существовал.

    12.02.2010
  • вы можете захотеть сделать это #define TRUE = (! (FALSE)) 15.03.2010
  • В чем преимущество #define TRUE = 1? 18.12.2012
  • Во-первых, не ставьте знак равенства (=) в #define. Во-вторых, только FALSE имеет определенное значение; нуль. ИСТИНА - любое другое значение. 08.03.2014

  • 11

    Никакой реальной разницы в скорости нет. Для компилятора они действительно одинаковы. Разница в том, что люди пытаются использовать и читать ваш код.

    Для меня это делает bool, true и false лучшим выбором в коде C ++. В коде C есть некоторые компиляторы, которые не поддерживают bool (мне часто приходится работать со старыми системами), поэтому в некоторых случаях я могу использовать определения.

    12.02.2010

    12

    1 наиболее читабелен, не совместим со всеми компиляторами.

    Ни один из компиляторов ISO C не имеет встроенного типа с именем bool. Компиляторы ISO C99 имеют тип _Bool и заголовок, соответствующий typedef bool. Таким образом, совместимость - это просто случай предоставления собственного заголовка, если компилятор не совместим с C99 (например, VC ++).

    Конечно, более простой подход - скомпилировать ваш код C как C ++.

    12.02.2010
  • Любой код C достаточной сложности не будет компилироваться с помощью компилятора C ++. Если вы хотите использовать компилятор C ++, используйте C ++. 20.04.2019
  • @Broman: Я не думаю, что сложность имеет какое-то отношение к этому; довольно тонкие смысловые различия. Более строгая проверка типов C ++ будет выдавать диагностику, которой не делает компиляция C. По большей части можно решить такие проблемы, и чтобы код был как действительным, так и семантически идентичным на обоих языках, и чаще всего результатом в любом случае будет лучший код. Но это правда, что большая (а не обязательно сложная) база кода C вряд ли будет скомпилирована без изменений. 20.04.2019
  • Верно, что дело не только в сложности. Я имел в виду, что большинство нетривиальных программ будет включать вызов malloc, а затем вам нужно выполнить приведение. Если вы собираетесь скомпилировать его с помощью компилятора C ++, почему бы вместо этого просто не написать код на C ++? 20.04.2019
  • @Broman Если вы скомпилируете его как C ++, это будет C ++, даже если он также действителен C. Использование malloc () и необходимость приведения - это один из примеров, когда создание C-кода, компилируемого в C ++, приводит к незначительно хуже C кода. 20.04.2019
  • @Broman Более того, это очень старый ответ. На данный момент VC ++ имеет гораздо более полную поддержку C99, включая stdbool.h. Отказ от C ++ действительно применяется только в том случае, если вы застряли на C90, что становится все более маловероятным. 20.04.2019

  • 13

    Я предпочитаю третье решение, то есть использование 1 и 0, потому что оно особенно полезно, когда вам нужно проверить, истинно ли условие или нет: вы можете просто использовать переменную для аргумента if.
    Если вы используете другие методы , Я думаю, что для согласования с остальной частью кода мне следует использовать такой тест:

    if (variable == TRUE)
    {
       ...
    }
    

    вместо:

    if (variable)
    {
       ...
    }
    
    12.02.2010

    14

    Я предпочитаю использовать

    #define FALSE (0!=0) 
    #define TRUE  (0==0)
    

    или прямо в коде

    if (flag == (0==0)) { ... }
    

    Об этом позаботится компилятор. Я использую много языков, и необходимость помнить, что FALSE равно 0, меня очень беспокоит; но если нужно, я обычно думаю об этом строковом цикле

    do { ... } while (*ptr);
    

    и это приводит меня к выводу, что FALSE равно 0

    24.04.2019

    15
  • Я заметил, что сравнения с ИСТИННЫМ не работают с неинициализированными переменными. Лучше инициализировать ваши логические значения и сравнить с FALSE. Перечисление лучше, если вам действительно нужно три значения; нет, да, и незнаю. Инициализируйте перечисление как donotknow. Не относитесь к перечислению как к логическому. Это не так. 01.09.2013
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..


    © 2024 nano-hash.ru, Nano Hash - криптовалюты, майнинг, программирование