Почему шестнадцатеричные числа с префиксом 0x?

414

Почему шестнадцатеричные числа начинаются с префикса 0x? Я понимаю использование префикса, но не понимаю, почему 0xбыл выбран.

unj2
источник
9
Теперь я понимаю, что заголовок и текст задают два совершенно разных вопроса. Большинство ответов сосредоточены на вопросе в заголовке. Ответ на вопрос в тексте - просто «это ничего не значит - это просто префикс, сообщающий компилятору, что целое число записано в шестнадцатеричном формате».
Андреас Рейбранд
30
Чтобы быть педантичным, можно также интерпретировать вопрос в названии двумя различными способами: 1) «Почему шестнадцатеричные числа имеют префикс 0x, а не любой другой префикс или индикатор?» 2) «Зачем нам нужно использовать префикс при вводе шестнадцатеричных чисел? Конечно, компилятор распознает 58A как шестнадцатеричное число даже без префикса?» Ответ на вторую интерпретацию вопроса тривиален. «123» также является шестнадцатеричным числом.
Андреас Рейбранд

Ответы:

440

Короткая история: The 0сообщает парсеру, что имеет дело с константой (а не идентификатором / зарезервированным словом). Что-то все еще необходимо для определения числовой базы: xэто произвольный выбор.

Длинная история: в 60-х годах преобладающие системы чисел программирования были десятичными и восьмеричными - у мэйнфреймов было 12, 24 или 36 бит на байт, что хорошо делится на 3 = log2 (8).

Язык BCPL использовал синтаксис 8 1234для восьмеричных чисел. Когда Кен Томпсон создал B из BCPL, он использовал 0вместо этого префикс. Это здорово, потому что

  1. целочисленная константа теперь всегда состоит из одного токена,
  2. парсер все еще может сразу сказать, что у него есть константа,
  3. парсер может сразу сказать базу ( 0одинаково в обеих базах),
  4. математически вменяемый ( 00005 == 05), и
  5. не нужно никаких ценных специальных символов (как в #123).

Когда C был создан из B, возникла необходимость в шестнадцатеричных числах (PDP-11 имел 16-битные слова), и все вышеперечисленные пункты все еще были в силе. Поскольку восьмерики все еще были нужны для других машин, 0xбыл выбран произвольно ( 00вероятно, было исключено, что это неудобно).

C # является потомком C, поэтому он наследует синтаксис.

Řrřola
источник
112
Я не думаю , что 0xнад 00было предпочтение / неловкости. 00сломал бы существующий код. 0010как восьмеричный 8, тогда 0010как шестнадцатеричный 16. Они не могли использовать любое число в качестве индикатора второй цифры (кроме 8или 9, и ни одно из них не имеет никакого значения, связанного с шестнадцатеричной), поэтому буква обязательна. И это оставляет либо 0hили 0x( H e X idecimal). С этого момента кажется, что он действительно вернулся к предпочтениям.
GManNickG
23
Использование 0префикса для восьмеричного кода на протяжении многих лет вызывало очень много проблем. Особенно в таких странах, как Великобритания, где номера телефонов начинаются с 0. Javascript и многие другие языки будут анализировать их как восьмеричные, искажая число перед сохранением. Чтобы добавить к веселью, один популярный продукт базы данных будет молча переключаться обратно на десятичный анализ, если число содержит 8или 9.
Basic
1
12, 24 и 36 также делятся на 4, так почему же они не думают о шестнадцатеричном?
phuclv
4
@ LưuVĩnhPhúc Вероятно, потому что шестнадцатеричное не очень важно. Большая часть аппаратного, программного обеспечения и документации того времени гораздо лучше соответствуют восьмеричным. BCPL был впервые реализован на 36-битном IBM 7094 с форматом инструкции, разделенным на две 3-битные части и 2 15-битные части; 6 битных символов; и документация в восьмеричном. Ранние реализации B были на PDP-7 (18 бит) и Honeywell GE-945 (36 бит, но с 18-битной адресацией и поддержкой 6 и 9-битных байтов). 16-битный PDP-11 вышел после B, поэтому не сильно повлиял на дизайн B.
8bittree
97

Примечание: я не знаю правильного ответа, но ниже приведены только мои личные предположения!

Как уже упоминалось, 0 перед числом означает, что оно восьмерично:

04524 // octal, leading 0

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

8000h // hex
FF00h // oops - valid identifier!  Hex or a variable or type named FF00h?

Вы не можете вести с персонажем по той же причине:

xFF00 // also valid identifier

Использование хеша, вероятно, было отброшено, поскольку оно конфликтует с препроцессором:

#define ...
#FF00 // invalid preprocessor token?

В конце концов, по какой-то причине, они решили поставить x после ведущего 0, чтобы обозначить шестнадцатеричное. Это недвусмысленно, поскольку все еще начинается с цифры, поэтому не может быть допустимым идентификатором, и, вероятно, основано на восьмеричном соглашении ведущего 0.

0xFF00 // definitely not an identifier!
AshleysBrain
источник
3
Интересно. Я предполагаю, что они могли использовать начальный 0 и конечный h, чтобы обозначить гекс. Конечный h, вероятно, был бы перепутан с суффиксом спецификатора типа, например, 0xFF00l против 0FF00hl
zdan
2
Этот аргумент подразумевает, что использование начального нуля для обозначения восьмеричных чисел предшествует использованию шестнадцатеричного префикса «0x». Это правда?
Андреас Рейбранд
1
Разве они не были изобретены одновременно? Почему когда-либо один, а не другой?
AshleysBrain
AshleysBrain см. Ответ @ Řrřola о том, почему может быть восьмеричное, но не шестнадцатеричное в одно и то же время.
jv42
2
@zdan они использовали это давным-давно. В сборке Intel x86 шестнадцатеричный литерал всегда должен начинаться с 0, если они начинаются с символа. Например, 0xFFAB1234должно быть написано как 0FFAB1234h. Я помню это из встроенного ассама в Паскале, когда я был молодым stackoverflow.com/q/11733731/995714
phuclv
27

Это префикс, указывающий, что число указано в шестнадцатеричном формате, а не в какой-либо другой базе. Язык программирования C использует его, чтобы сообщить компилятору.

Пример:

0x6400переводит на 6*16^3 + 4*16^2 + 0*16^1 +0*16^0 = 25600. Когда чтение компилятора 0x6400, он понимает, что число является шестнадцатеричным с помощью 0x термин. Обычно мы можем понять по (6400) 16 или (6400) 8 или как угодно ..

Для двоичного файла это будет:

0b00000001

Надеюсь, я помог каким-то образом.

Добрый день!

Лойола
источник
2
Двоичные литералы поддерживаются только в C ++, начиная с C ++ 14, и вообще не поддерживаются в C.
Руслан
1
Это не объясняет почему . В частности, почему вы не могли написать первый пример как x6400? Это xвсе еще может быть использовано для вывода шестнадцатеричного.
Аарон Франке
12

Предыдущий 0 используется для обозначения числа в базе 2, 8 или 16.

На мой взгляд, 0x было выбрано для обозначения гекса, потому что «х» звучит как гекс.

Просто мое мнение, но я думаю, что это имеет смысл.

Хорошего дня!

Джонни Лоу
источник
2
Спасибо за ответ! Я понимаю, что это ваш первый пост в StackOverflow. Ответ мог бы быть более полезным, если бы мнения отличались от фактов.
vivek_ganesan