2010-02-22 12 views
14

Questo è più di un linguaggio design piuttosto che una domanda di programmazione.Qual è la ragione per cui i linguaggi di alto livello come C#/Java mascherano l'operando del conteggio a spostamento di bit?

Il seguente è un estratto da JLS 15.19 Shift Operators:

Se il tipo promosso dell'operando di sinistra è int, solo i cinque bit più basso ordine dell'operando di destra vengono utilizzati per lo shift .

Se il tipo di promotore dell'operando di sinistra è long, solo i sei bit di ordine inferiore dell'operando di destra vengono utilizzati come distanza di spostamento.

Questo comportamento è anche specified in C#, e mentre io non sono sicuro se è nelle specifiche ufficiali per Javascript (se c'è uno), è anche vero in base alla mia prova, almeno.

La conseguenza è che le seguenti condizioni:

(1 << 32) == 1 

comprendo che questa specifica è probabilmente "ispirato" dal fatto che l'hardware sottostante richiede solo 5 bit per l'operando conteggio quando lo spostamento a 32 bit valori (e 6 bit per 64 bit), e posso capire un comportamento del genere specificato a livello di JVM per esempio, ma perché i linguaggi di alto livello come C# e Java mantengono questo comportamento piuttosto di basso livello? Non dovrebbero fornire una visione più astratta oltre l'implementazione hardware e comportarsi in modo più intuitivo? (Ancora meglio se possono assumere un conteggio negativo per significare spostarsi nella direzione ALTRO!)

risposta

8

Java e C# non sono completamente "di alto livello". Cercano davvero di essere tali da poter essere compilati in codice efficiente, al fine di brillare in micro-benchmark. Questo è il motivo per cui hanno i "tipi di valore" come int invece di avere, come tipo intero predefinito, interi veri, che sarebbero oggetti a sé stanti e non limitati a un intervallo fisso.

Quindi, imitano quello che fa l'hardware. Lo ritagliano un po ', nel senso che sono mandare il mascheramento, mentre C lo consente. Ancora, Java e C# sono lingue "di medio livello".

+0

Determinare se una lingua sia di alto livello o meno è molto soggettiva, ho capito. Penserei, tuttavia, che la maggior parte delle persone classifichi Java e C# come "alta", almeno per i linguaggi non di scripting. – polygenelubricants

+0

Assolutamente. Ma Java e C# conservano ancora le caratteristiche di basso livello, per efficienza (o almeno _ efficienza percepita_). Il tipo 'int' a 32 bit e il mascheramento del numero di turni sono tali caratteristiche. Altre lingue, come Scheme, sono "di livello superiore" in questa materia. –

+0

http://therighttool.hammerprinciple.com/statements/this-is-a-high-level-language – starblue

5

Perché nella maggior parte degli ambienti di programmazione un numero intero è di soli 32 bit. Quindi 5 bit (che è sufficiente per esprimere 32 valori) sono già sufficienti per spostare l'intero intero. Un ragionamento simile esiste per una lunghezza di 64 bit: 6 bit è tutto ciò che serve per spostare completamente l'intero valore.

Riesco a capire parte della confusione: se il tuo operando di destra è il risultato di un calcolo che ha un valore maggiore di 32, potresti aspettarti di spostare solo tutti i bit anziché applicare una maschera.

+0

Capisco il motivo per cui lo spostamento di un valore a 32 bit richiede solo 5 bit al massimo, e qualsiasi cosa oltre a ciò cancella essenzialmente l'intero registro e, come utente del linguaggio, a volte è esattamente quello che voglio! Come ho detto, la domanda non è perché i parametri vengono scelti come tali, ma piuttosto perché qualcosa di così basso livello viene mantenuto nel linguaggio di alto livello. – polygenelubricants

+0

'se il tuo operando di destra è il risultato di un calcolo che finisce con un valore maggiore di 32' ... 5 bit possono memorizzare valori 0 ~ 31, quindi non è semplicemente possibile spostare di 32 bit, né farebbe quindi sii utile, poiché un semplice 'xor reg, reg' otterrebbe lo stesso effetto. –

5

C# e Java definiscono lo spostamento come utilizzando solo i bit di ordine basso del numero di shift, poiché è ciò che fanno entrambe le istruzioni di spostamento di sparc e x86. Java è stato originariamente implementato da Sun sui processori sparc e C# da Microsoft su x86.

Al contrario, C/C++ lascia come indefinito il comportamento delle istruzioni di spostamento se il numero di turni non è compreso nell'intervallo 0,31 (per un int di 32 bit), consentendo qualsiasi comportamento. Questo perché quando C è stato implementato per la prima volta, diversi handware li hanno gestiti in modo diverso. Ad esempio, su un VAX, lo spostamento di un valore negativo sposta l'altra direzione. Quindi con C, il compilatore può semplicemente usare l'istruzione di spostamento dell'hardware e fare qualsiasi cosa.