Почему в C не было логического типа данных до C99? - PullRequest
39 голосов
/ 11 марта 2010

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

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

Ответы [ 11 ]

25 голосов
/ 12 марта 2010

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

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

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

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

(Выделение мое.)

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

17 голосов
/ 11 марта 2010

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

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

11 голосов
/ 11 марта 2010

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

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

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

10 голосов
/ 11 марта 2010

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

7 голосов
/ 11 марта 2010

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

6 голосов
/ 11 марта 2010

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

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

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

5 голосов
/ 12 марта 2010

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

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

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

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

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

4 голосов
/ 11 марта 2010

Исторические причины, вероятно:

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

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

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

2 голосов
/ 24 октября 2017

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

someBool = intFunction();
someInt = someBool;

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

someChar = intFunction();
someInt = someChar;

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

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

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

1 голос
/ 11 марта 2010

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

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

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

...