Dlaczego liczby szesnastkowe są poprzedzone 0x?

414

Dlaczego liczby szesnastkowe mają prefiks jako 0x? Rozumiem użycie przedrostka, ale nie rozumiem znaczenia, dlaczego 0xzostał wybrany.

unj2
źródło
9
Teraz zdaję sobie sprawę, że tytuł i tekst zadają dwa zupełnie różne pytania. Większość odpowiedzi skupia się na pytaniu w tytule. Odpowiedź na pytanie w tekście brzmi: „to nic nie znaczy - to tylko przedrostek informujący kompilator, że liczba całkowita jest zapisywana w systemie szesnastkowym”.
Andreas Rejbrand
30
Aby być pedantycznym, można również interpretować pytanie w tytule na dwa różne sposoby: 1) „Dlaczego liczby szesnastkowe mają prefiks 0x, a nie jakikolwiek inny prefiks lub wskaźnik?” 2) „Dlaczego musimy używać prefiksu podczas wprowadzania liczb szesnastkowych? Z pewnością kompilator rozpozna 58A jako liczbę szesnastkową nawet bez prefiksu?” Odpowiedź na drugą interpretację pytania jest trywialna. „123” jest także liczbą szesnastkową.
Andreas Rejbrand

Odpowiedzi:

440

Krótka historia:0 mówi parser to do czynienia ze stałą (i nie identyfikator / zastrzeżone wyrazu). Potrzebne jest jeszcze coś, aby określić podstawę liczb: xjest to arbitralny wybór.

Długa historia: w latach 60-tych powszechne systemy liczb programowych były dziesiętne i ósemkowe - komputery mainframe miały 12, 24 lub 36 bitów na bajt, co można łatwo podzielić przez 3 = log2 (8).

W języku BCPL zastosowano składnię 8 1234liczb ósemkowych. Kiedy Ken Thompson utworzył B z BCPL, 0zamiast tego użył przedrostka. To świetnie, ponieważ

  1. stała liczb całkowitych składa się teraz zawsze z jednego tokena,
  2. parser wciąż może od razu powiedzieć, że ma stałą,
  3. parser może natychmiast powiedzieć bazie ( 0jest taki sam w obu bazach),
  4. jest matematycznie rozsądny ( 00005 == 05) i
  5. żadne cenne znaki specjalne nie są potrzebne (jak w #123).

Kiedy C utworzono z B, pojawiła się potrzeba liczb szesnastkowych (PDP-11 miał 16-bitowe słowa) i wszystkie powyższe punkty były nadal aktualne. Ponieważ ósemki były nadal potrzebne dla innych maszyn, 0xzostał wybrany arbitralnie ( 00prawdopodobnie został wykluczony jako niezręczny).

C # jest potomkiem C, więc dziedziczy składnię.

Řrřola
źródło
112
Nie sądzę 0xponad 00był preferencji / nieporadność. 00zepsułby istniejący kod. 0010jak ósemkowy 8, a 0010jak szesnastkowy 16. Nie mogli użyć żadnej liczby jako wskaźnika drugiej cyfry (z wyjątkiem 8lub 9, i żadna nie ma żadnego znaczenia związanego z liczbą szesnastkową), więc litera jest koniecznością. I to pozostawia albo 0halbo 0x( H e X idecimal). Od tego momentu wydaje się, że naprawdę wraca do preferencji.
GManNickG
23
Używanie 0przedrostka ósemkowego spowodowało tak wiele problemów na przestrzeni lat. Zwłaszcza w krajach takich jak Wielka Brytania, gdzie numery telefonów zaczynają się od 0. JavaScript i wiele innych języków parsuje je jako liczby ósemkowe, zmieniając liczbę przed zapisaniem. Aby dodać do zabawy, jeden popularny produkt bazy danych po cichu przestawiłby się na parsowanie dziesiętne, jeśli liczba zawierała 8lub 9.
Podstawowy
1
12, 24 i 36 są również podzielne przez 4, więc dlaczego nie pomyśleli o tym w systemie szesnastkowym?
phuclv
4
@ LưuVĩnhPhúc Prawdopodobnie dlatego, że szesnastkowy nie był zbyt istotny. Większość sprzętu, oprogramowania i dokumentacji w tamtym czasie jest znacznie lepsza. BCPL został po raz pierwszy zaimplementowany w 36-bitowym IBM 7094 , z formatem instrukcji podzielonym na dwie 3-bitowe części i 2 15-bitowe części; 6-bitowe znaki; i dokumentacja ósemkowa. Wczesne implementacje B były na PDP-7 (18 bitów) i Honeywell GE-945 (36 bitów, ale z 18-bitowym adresowaniem i obsługą 6 i 9 bitów). 16-bitowy PDP-11 wyszedł po B, więc nie miałby większego wpływu na projekt B.
8bittree
97

Uwaga: nie znam poprawnej odpowiedzi, ale poniżej to moja osobista spekulacja!

Jak wspomniano 0 przed liczbą oznacza, że ​​jest ósemkowa:

04524 // octal, leading 0

Wyobraź sobie, że musisz opracować system oznaczania liczb szesnastkowych i zauważ, że pracujemy w środowisku typu C. Co powiesz na zakończenie h jak montaż? Niestety nie możesz - pozwoliłoby ci to tworzyć tokeny, które są poprawnymi identyfikatorami (np. Możesz nazwać zmienną to samo), co powodowałoby nieprzyjemne niejasności.

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

Nie możesz prowadzić postacią z tego samego powodu:

xFF00 // also valid identifier

Używanie skrótu zostało prawdopodobnie wyrzucone, ponieważ powoduje konflikt z preprocesorem:

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

Ostatecznie, z jakiegokolwiek powodu, postanowili wstawić x po wiodącym 0, aby oznaczyć szesnastkowo. Jest to jednoznaczne, ponieważ wciąż zaczyna się od znaku liczbowego, więc nie może być prawidłowym identyfikatorem i prawdopodobnie opiera się na konwencji ósemkowej wiodącego 0.

0xFF00 // definitely not an identifier!
AshleysBrain
źródło
3
Ciekawy. Wyobrażam sobie, że mogliby użyć wiodącego 0 i końcowego h do oznaczenia heksa. Końcowy h prawdopodobnie zostałby pomylony z przyrostkiem specyfikatora typu, np. 0xFF00l vs 0FF00hl
zd.
2
Ten argument sugeruje, że użycie wiodącego zera do oznaczenia liczb ósemkowych poprzedza użycie szesnastkowego prefiksu „0x”. Czy to prawda?
Andreas Rejbrand
1
Czy nie zostałyby wymyślone w tym samym czasie? Dlaczego miałoby być jedno, ale nie drugie?
AshleysBrain
AshleysBrain patrz odpowiedź @ Řrřola, aby dowiedzieć się, dlaczego może być ósemkowa, ale nie szesnastkowa w tym samym czasie.
jv42
2
@zdan używali go dawno temu. W zespole Intel x86 literał szesnastkowy musi być zawsze poprzedzony cyfrą 0, jeśli zaczyna się od znaku. Na przykład 0xFFAB1234należy zapisać jako 0FFAB1234h. Pamiętam to z wbudowanego asm w Pascalu, kiedy byłem młody stackoverflow.com/q/11733731/995714
phuclv
27

Jest to przedrostek wskazujący, że liczba jest szesnastkowa, a nie w innej bazie. Język programowania C używa go do informowania kompilatora.

Przykład:

0x6400tłumaczy się 6*16^3 + 4*16^2 + 0*16^1 +0*16^0 = 25600. Kiedy kompilator czyta 0x6400, rozumie, że liczba jest szesnastkowa za pomocą 0x warunku . Zwykle możemy zrozumieć przez (6400) 16 lub (6400) 8 lub cokolwiek ...

W przypadku pliku binarnego byłoby to:

0b00000001

Mam nadzieję, że w jakiś sposób pomogłem.

Dobry dzień!

Loyola
źródło
2
Literały binarne są obsługiwane tylko w C ++ od C ++ 14 i wcale nie są obsługiwane w C.
Ruslan
1
To nie wyjaśnia, dlaczego . W szczególności dlaczego nie mógłbyś napisać pierwszego przykładu jako x6400? xNadal może być wykorzystywany do wywnioskować szesnastkowo.
Aaron Franke
12

Poprzednie 0 służy do wskazania liczby w podstawie 2, 8 lub 16.

Moim zdaniem wybrano 0x, aby wskazać hex, ponieważ „x” brzmi jak hex.

Po prostu moja opinia, ale myślę, że to ma sens.

Dobry dzień!

Johnny Low
źródło
2
Dziękuję za odpowiedź! Rozumiem, że to twój pierwszy post na StackOverflow. Odpowiedź mogłaby być bardziej pomocna, gdyby opinie były oddzielone od faktów.
vivek_ganesan