Еще раз, я преподаю класс, где я могу ответить на вопросы студентов о C. Здесь один я не знаю ответа на вопрос: было ли обоснование принятия signed
в качестве модификатора по умолчанию для C? Казалось бы, unsigned
был естественным выбором. Итак, это действительно дизайнерское решение?
Подписанное по умолчанию в C
Ответ 1
В терминах стандарта (так как ваш вопрос помечен как таковой), signed
был помечен как значение по умолчанию, так как это было с реализациями C, которые появились перед стандартом.
Первоначальные стандартные требования ANSI/ISO заключались в том, чтобы кодифицировать существующую практику, а не создавать новый язык. Поэтому поведение предстандартных реализаций было самым важным фактором в соответствии с обоснованным документом:
В оригинальном уставе X3J11 четко предусмотрена кодификация общей существующей практики, а Комитет C89 быстро придерживался прецедента там, где это было ясно и недвусмысленно.
Подавляющее большинство языков, определенных C89, было точно таким же, как определено в Приложении A первого выпуска языка программирования C Брайаном Керниганом и Деннисом Ритчи и реализовано почти во всех переводчиках того времени. (Этот документ в дальнейшем именуется K & R.)
Если вы хотите узнать, почему предпочтительные варианты перед стандартными версиями signed
, вам, вероятно, придется изучить архитектуру машин PDP-n, для которых были разработаны UNIX и C.
Страница История C показывает, что unsigned
был на самом деле относительным опозданием на язык, появляющимся когда-то в середине 70-х:
В течение 1973-1980 гг. язык немного вырос: структура типов приобрела неподписанные, длинные, объединенные и перечисляемые типы, а структуры стали почти первоклассными объектами (отсутствовали только нотации для литералов).
Ответ 2
В основном это касается обратной совместимости и спуска с более ранних языков, которые не могли легко поддерживать как подписанные, так и целые числа без знака.
C был получен из более старого языка B, который был получен из еще более старого языка, называемого BCPL (который был упрощенной версией CPL).
BCPL был в значительной степени нетипизированным языком. Объявление переменной не указывало тип объекта; скорее, операция над данной переменной будет относиться к ней так, как если бы она имела заданный тип.
Операторы BCPL +
, -
, *
, /
и REM
обработали свои операнды как целые числа и дали целочисленные результаты.
Если BCPL поддерживал целые числа без знака, то либо он должен был иметь другой набор операторов без знака операндов, либо вообще не мог бы представлять отрицательные числа. (Обратите внимание, что BCPL не поддерживает точку с плавающей запятой.)
СинтаксисB сильно отличался от BCPL (и ближе к C), но он сохранил большую часть той же семантики. В частности, переменные и функции были по умолчанию целочисленными типами - и не было ключевого слова unsigned
.
Ранняя C, основанная на B, также не имела ключевого слова unsigned
. Он имел только четыре основных числовых типа: char
, int
, float
и double
. (unsigned
было добавлено вместе с long
, union
и enum
, некоторое время между 1973 и 1980 годами.) Учитывая слабо типизированный характер языка, программисты иногда использовали указатели, когда им нужна арифметика без знака.
"Функция", в которой объект без объявленного типа неявно имеет тип int
, был сохранен в C до тех пор, пока стандарт ISO 1999 года окончательно не удалил правило "неявное int
".
Кроме того, знаковые целочисленные типы просто более полезны, чем неподписанные типы. Способность представлять отрицательные значения может быть чрезвычайно удобной. Учитывая типичную семантику wraparound, ошибка в беззнаковом вычитании двух небольших значений может дать огромное положительное значение (3 - 4 == 65535
например, для 16-разрядного неподписанного типа). Даже в области системного программирования, являющейся главной целью всех этих языков, иногда необходимо представлять отрицательные значения (например, изменение в некотором количестве).
Литература:
Ответ 3
Согласно "Развитие языка C" , понятие unsigned было расширением языка, когда к нему добавлялись функции между 1973 годом и 1980 год. Хотя это явно не указано, повествование предполагает, что оно не было введено до 1977 года (см. Переносимость, пункт 3).
Таким образом, дефолт по умолчанию был связан с тем, что язык первоначально имел только подписанные типы.
Ответ 4
Подтверждение по умолчанию char
не определяется языком. Он определяется реализацией. Некоторые процессоры более естественно подписаны char, а другие более естественно без знака.
Ответ 5
unsigned
гарантируется, что семантика будет проще: по модулю base-2 n без каких-либо исключений. Но не делайте предположений о том, что такое n: размер диапазона не требуется равным размеру соответствующего подписанного типа.
Единственное требование состоит в том, что все положительные знаковые значения также могут быть представлены соответствующим неподписанным типом.
Одной из допустимых реализаций unsigned
будет использование арифметики с подписью с двумя дополнениями и без знака после каждой операции. Это вряд ли появится в реальной жизни, но машины с арифметикой с не-двумя дополнениями могут иметь больше проблем, пытаясь обойти отрицательную логику числа.
На практике отрицательные числа являются важной особенностью любой аппаратной платформы, но способность обрабатывать весь регистр как положительное число - это просто обледенение на торте. C предназначен для наиболее плотного обтекания наиболее эффективных частей оборудования.