Подтвердить что ты не робот

Почему C не имел тип булевых данных до C99?

Я понимаю, что вы можете просто #define некоторые целые числа, но почему C не имел выделенный тип булевых данных до C99?

Это такое обычное явление в программировании и логике, я не понимаю отсутствие явного типа и обозначения.

4b9b3361

Ответ 1

Если вы проводите немного времени в библиотеке, вам не нужно спекулировать. Вот некоторые утверждения, взятые из документ Дениса Ричи об эволюции C. Контекст заключается в том, что Деннис строит на языке Кена Томпсона B, который был реализован на очень маленькой PDP-7, машине, написанной по словам. Из-за растущего интереса группа получила один из первых PDP-11. Деннис пишет:

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

Модель B и BCPL подразумевала накладные расходы при работе с указателями: языковые правила, определяя указатель как индекс в массиве слов, принудительные указатели должны быть представлены как индексы слов. Каждая ссылка указателя генерировала преобразование шкалы времени выполнения из указателя в адрес байта, ожидаемый аппаратным обеспечением.

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

(Подчеркните мой.)

Далее в статье описывается, как Деннис пытается изобрести новую семантику указателя, заставить массивы работать и смириться с этой новомодной идеей struct. Понятия безопасности типов и различения булевых чисел от целых чисел не казались важными до гораздо позже: -)

Ответ 2

C на самом деле немного больше, чем язык ассемблера более высокого уровня. Да, он получил контрольные структуры и много чего, и даже получил типы, которые ассемблеру, разумеется, не нужны.

Но язык был разработан несколько десятилетий назад. И поскольку каждый логический результат сводится к отдельным битам в слове состояния процессора, очевидно, этого было достаточно, чтобы просто использовать для него целостный тип данных. И это сделало компилятор, вероятно, немного менее сложным, так как вы можете опустить некоторую проверку типов (в более поздних структурах управления версиями требуется логическое значение, на C им просто нужно интегральное значение либо 0, либо что-то еще).

Ответ 3

Было распространено (и все еще в некоторых случаях) рассматривать ноль как ложное и любое ненулевое значение как истину. Это имеет преимущества для сокращения: например, вместо while (remaining != 0) вы можете просто использовать while (remaining).

Некоторые языки, стандартизированные на true, являются -1. Причиной этого является то, что в двухзадачной нотации (которую большинство компьютеров используют для представления отрицательных чисел), побитовое, а не 0, равно -1 (в 8-битном двоичном, 11111111 - десятичном -1).

С течением времени было осознано, что использование константы, определяемой компилятором, предотвратило бы много путаницы. Прошло некоторое время с тех пор, как я сделал С++, но я уверен, что любое ненулевое значение по-прежнему будет оценивать "true".

Ответ 4

Процессор не имеет "логического типа", он работает только с байтами и кратным им, поэтому логический тип не имел смысла в то время, поскольку он не давал преимущества (зачем использовать тип, когда вы можете только проверить "0" или "не равно нулю" )

Ответ 5

Я подозреваю, что было сочтено достаточным, чтобы иметь целочисленный тип, причем 0 является ложным и ничего не равным 0.

Ответ 6

Тип, который вы используете для хранения логических (обычно), включает компромисс между пространством и временем. Обычно вы получаете самые быстрые результаты (по крайней мере, для отдельной операции), используя int (обычно четыре байта). С другой стороны, если вы используете очень много, это может сделать больше смысла использовать один байт или даже упаковать их, поэтому каждое значение, которое вы храните, использует только один бит, но когда/если вы это сделаете, чтение или запись одного бита становится значительно дороже.

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

Таким образом, реальный вопрос заключается в том, почему в C99 был добавлен булев тип. Я предполагаю, что речь идет о нескольких факторах. Во-первых, они поняли, что удобство для программиста теперь, как правило, более важно, что дает абсолютную максимальную производительность. Во-вторых, компиляторы теперь выполняют довольно немного глобальный анализ, поэтому, по крайней мере, можно предположить, что кто-то может написать компилятор, который пытается выбрать представление, наиболее подходящее для конкретной программы (хотя я не знаю, что действительно делает).

Ответ 7

Старый C на самом деле не "пропустил" логический тип - просто все интегральные типы также считались подходящими для выполнения двойной обязанности, хранения булевых. Я вижу две основные причины этого:

  • Процессоры с битовой адресацией не были вообще распространены (и до сих пор их нет), поэтому компилятор действительно не сможет использовать "истинный булевский" тип для сохранения любого пространства - логическое будет по-прежнему по крайней мере, не меньше, чем char (если вы надеетесь получить доступ к нему эффективно).

  • Типы, более узкие, чем int, все равно расширяются до int в выражениях, поэтому логические операторы будут работать с операндами int.

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

Помните, что язык C имеет набор операторов, которые производят логические результаты (определены как 0 или 1) - !, &&, ||, !=, ==, <, <=, > и >= - так что это только выделенный булев тип, который не существует.

Ответ 8

Исторические причины, возможно:

CPL, на который в значительной степени повлиял ALGOL, скорее всего, имел тип boolean, но моего google-fu не хватало, чтобы найти ссылку для этого. Но CPL был слишком амбициозен для своего времени, в результате чего была урезана версия под названием BCPL, которая имела то преимущество, что вы могли реально реализовать ее на доступном оборудовании.

У BCPL был только один тип - "слово", который был интерпретирован как ложный в булевых контекстах, если 0 и как истинный, если ~0 (что означает дополнение к 0, которое будет представлять значение -1 если интерпретируется как подписанное целое число с двумя дополнениями). Интерпретация любого другого значения была зависимой от реализации.

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

Ответ 9

Потому что они не ввели его. Извините, если это звучит сноппиком, но в основном он не был определен как таковой.

Помните, что большинство людей #define TRUE и FALSE.

Вы можете сказать, что стандарт bool IS - но, очевидно, он не был стандартным до C99, который был сделан 10 лет назад;) Они добавили его тогда, когда стало очевидным недостающий элемент.

Ответ 10

Добавление отдельного типа "Boolean", не совместимого с целыми числами, сделало бы компилятор более сложным, чем просто использование целых чисел для этой цели. Наличие отдельного булева типа, совместимого с целыми числами, позволяет указать возможные последствия хранения значения, отличного от 0 или 1 в объект Boolean, или выполнение числовых вычислений на булевом объект, представление которого не содержит ни одного битового шаблона, связанного с "0" или "1". Дано:

someBool = intFunction();
someInt = someBool;

требующий, чтобы someInt получил значение 1, если intFunction возвращает любое ненулевое значение, как правило, делает выше дороже, чем

someChar = intFunction();
someInt = someChar;

В тех случаях, когда потребуется бывшая семантика, они могут быть достигнуты без использования булевого типа через:

someChar = !!intFunction();
someInt = someChar;

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

Ответ 11

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