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ż
stała liczb całkowitych składa się teraz zawsze z jednego tokena,
parser wciąż może od razu powiedzieć, że ma stałą,
parser może natychmiast powiedzieć bazie ( 0jest taki sam w obu bazach),
jest matematycznie rozsądny ( 00005 == 05) i
ż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).
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.
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.
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 ...
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.
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.
Odpowiedzi:
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:x
jest 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 1234
liczb ósemkowych. Kiedy Ken Thompson utworzył B z BCPL,0
zamiast tego użył przedrostka. To świetnie, ponieważ0
jest taki sam w obu bazach),00005 == 05
) i#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,
0x
został wybrany arbitralnie (00
prawdopodobnie został wykluczony jako niezręczny).C # jest potomkiem C, więc dziedziczy składnię.
źródło
0x
ponad00
był preferencji / nieporadność.00
zepsułby istniejący kod.0010
jak ósemkowy8
, a0010
jak szesnastkowy16
. Nie mogli użyć żadnej liczby jako wskaźnika drugiej cyfry (z wyjątkiem8
lub9
, i żadna nie ma żadnego znaczenia związanego z liczbą szesnastkową), więc litera jest koniecznością. I to pozostawia albo0h
albo0x
( H e X idecimal). Od tego momentu wydaje się, że naprawdę wraca do preferencji.0
przedrostka ósemkowego spowodowało tak wiele problemów na przestrzeni lat. Zwłaszcza w krajach takich jak Wielka Brytania, gdzie numery telefonów zaczynają się od0
. 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ła8
lub9
.Uwaga: nie znam poprawnej odpowiedzi, ale poniżej to moja osobista spekulacja!
Jak wspomniano 0 przed liczbą oznacza, że jest ósemkowa:
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.
Nie możesz prowadzić postacią z tego samego powodu:
Używanie skrótu zostało prawdopodobnie wyrzucone, ponieważ powoduje konflikt z preprocesorem:
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.
źródło
0xFFAB1234
należy zapisać jako0FFAB1234h
. Pamiętam to z wbudowanego asm w Pascalu, kiedy byłem młody stackoverflow.com/q/11733731/995714Jest 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:
0x6400
tłumaczy się6*16^3 + 4*16^2 + 0*16^1 +0*16^0 = 25600.
Kiedy kompilator czyta0x6400
, 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ń!
źródło
x6400
?x
Nadal może być wykorzystywany do wywnioskować szesnastkowo.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ń!
źródło