Perché i numeri esadecimali hanno il prefisso 0x?


414

Perché i numeri esadecimali hanno il prefisso come 0x? Capisco l'uso del prefisso ma non capisco il significato del perché è 0xstato scelto.


9
Ora mi rendo conto che il titolo e il testo pongono due domande completamente diverse. La maggior parte delle risposte si concentra sulla domanda nel titolo. La risposta alla domanda nel testo è semplicemente "non significa nulla - è semplicemente un prefisso che dice al compilatore che l'intero è scritto in esadecimale".
Andreas Rejbrand,

30
Per essere pedanti, si potrebbe anche interpretare la domanda nel titolo in due modi diversi: 1) "Perché i numeri esadecimali hanno il prefisso 0x, al contrario di qualsiasi altro prefisso o indicatore?" 2) "Perché è necessario utilizzare un prefisso quando si inseriscono numeri esadecimali? Sicuramente il compilatore riconoscerà 58A come numero esadecimale anche senza il prefisso?" La risposta alla seconda interpretazione della domanda è banale. "123" è anche un numero esadecimale.
Andreas Rejbrand,

Risposte:


440

Breve storia: Il 0dice il parser è che fare con una costante (e non una parola identificatore / riservato). Qualcosa è ancora necessario per specificare la base numerica: xè una scelta arbitraria.

Lunga storia: negli anni '60, i sistemi di numerazione di programmazione prevalenti erano decimali e ottali - i mainframe avevano 12, 24 o 36 bit per byte, che è ben divisibile per 3 = log2 (8).

Il linguaggio BCPL usava la sintassi 8 1234per i numeri ottali. Quando Ken Thompson ha creato B da BCPL, ha usato 0invece il prefisso. Questo è fantastico perché

  1. una costante intera ora consiste sempre di un singolo token,
  2. il parser può ancora dire subito che ha una costante,
  3. il parser può dire immediatamente alla base ( 0è la stessa in entrambe le basi),
  4. è matematicamente sano ( 00005 == 05) e
  5. non sono necessari preziosi caratteri speciali (come in #123).

Quando C è stato creato da B, è emersa la necessità di numeri esadecimali (il PDP-11 aveva parole a 16 bit) e tutti i punti sopra erano ancora validi. Poiché gli ottali erano ancora necessari per altre macchine, 0xfu scelto arbitrariamente ( 00probabilmente fu escluso come imbarazzante).

C # è un discendente di C, quindi eredita la sintassi.


112
Non credo che 0xnel corso 00ero preferenza / disagio. 00romperebbe il codice esistente. 0010come ottale è 8, mentre 0010come esadecimale sarebbe 16. Non potevano usare alcun numero come indicatore di seconda cifra (eccetto 8o 9, e nessuno dei due ha alcun significato relativo all'esadecimale), quindi una lettera è un must. E questo lascia uno 0ho 0x( H e X idecimale). Da questo punto sembra che sia davvero tornato alle preferenze.
GManNickG


23
L'uso di un 0prefisso per ottale ha causato così tanti problemi nel corso degli anni. In particolare in paesi come il Regno Unito dove i numeri di telefono iniziano con a 0. Javascript e molte altre lingue li analizzerebbero come ottali, modificando il numero prima di memorizzarli. Per aggiungere al divertimento, un popolare prodotto di database tornerebbe silenziosamente all'analisi decimale se il numero contenesse un 8o 9.
Base

1
12, 24 e 36 sono anche divisibili per 4, quindi perché non hanno pensato all'esadecimale per quello?
phuclv,

4
@ LưuVĩnhPhúc Probabilmente perché esadecimale non era molto rilevante. La maggior parte dell'hardware, del software e della documentazione dell'epoca si adattano molto meglio all'ottale. BCPL è stato inizialmente implementato su un IBM 7094 a 36 bit , con un formato di istruzione suddiviso in due parti a 3 bit e 2 parti a 15 bit; Caratteri a 6 bit; e documentazione in ottale. Le prime implementazioni di B erano su un PDP-7 (18 bit) e un Honeywell GE-945 (36 bit, ma con indirizzamento a 18 bit e supporto per byte a 6 e 9 bit). Il PDP-11 a 16 bit è uscito dopo B, quindi non avrebbe influenzato molto il design di B.
8

97

Nota: non conosco la risposta corretta, ma il seguito è solo la mia speculazione personale!

Come è stato menzionato uno 0 prima che un numero significhi che è ottale:

04524 // octal, leading 0

Immagina di dover inventare un sistema per indicare numeri esadecimali e nota che stiamo lavorando in un ambiente in stile C. Che ne dici di finire con h come assembly? Sfortunatamente non puoi - ti permetterebbe di creare token che sono identificatori validi (es. Potresti nominare una variabile la stessa cosa) che renderebbe alcune brutte ambiguità.

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

Non puoi guidare un personaggio per lo stesso motivo:

xFF00 // also valid identifier

L'uso di un hash è stato probabilmente eliminato perché in conflitto con il preprocessore:

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

Alla fine, per qualsiasi motivo, hanno deciso di inserire una x dopo uno 0 iniziale per indicare esadecimale. È inequivocabile poiché inizia ancora con un carattere numerico, quindi non può essere un identificatore valido ed è probabilmente basato sulla convenzione ottale di uno 0 iniziale.

0xFF00 // definitely not an identifier!

3
Interessante. Immagino che avrebbero potuto usare uno 0 AND trailing iniziale per indicare hex. Probabilmente il trailing h sarebbe stato confuso con il suffisso dell'identificatore di tipo, ad esempio 0xFF00l vs 0FF00hl
zdan

2
Questo argomento implica che l'uso di uno zero iniziale per indicare i numeri ottali precede l'uso del prefisso "0x" esadecimale. È vero?
Andreas Rejbrand,

1
Non sarebbero stati entrambi inventati allo stesso tempo? Perché mai ci sarebbe mai stato uno ma non l'altro?
AshleysBrain,

AshleysBrain vede la risposta di @ Řrřola sul perché ci potrebbe essere ottale ma non esadecimale allo stesso tempo.
jv42

2
@zdan l'hanno usato molto tempo fa. Nell'assembly Intel x86 un letterale esadecimale deve sempre essere preceduto da 0 se iniziano con un carattere. Ad esempio 0xFFAB1234deve essere scritto come 0FFAB1234h. Me lo ricordo da asm inline in Pascal quando ero giovane stackoverflow.com/q/11733731/995714
phuclv

27

È un prefisso per indicare che il numero è in esadecimale piuttosto che in qualche altra base. Il linguaggio di programmazione C lo usa per dire al compilatore.

Esempio:

0x6400si traduce in 6*16^3 + 4*16^2 + 0*16^1 +0*16^0 = 25600. Quando il compilatore legge 0x6400, Comprende che il numero è esadecimale con l'aiuto del termine 0x . Di solito possiamo capire da (6400) 16 o (6400) 8 o qualsiasi altra cosa.

Per binario sarebbe:

0b00000001

Spero di aver aiutato in qualche modo.

Buona giornata!


2
I letterali binari sono supportati solo in C ++ da C ++ 14 e non supportati affatto in C.
Ruslan,

1
Questo non spiega perché . In particolare, perché non hai potuto scrivere il primo esempio come x6400? Il xpoteva ancora essere utilizzato per inferire esadecimale.
Aaron Franke,

12

Lo 0 precedente viene utilizzato per indicare un numero in base 2, 8 o 16.

Secondo me, 0x è stato scelto per indicare hex perché 'x' suona come hex.

Solo la mia opinione, ma penso che abbia senso.

Buona giornata!


2
Grazie per la risposta! Capisco che questo è il tuo primo post su StackOverflow. La risposta avrebbe potuto essere più utile se le opinioni fossero separate dai fatti.
vivek_ganesan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.