2011-12-29 13 views
9

Ad esempio, perché long int ha un modificatore letterale, ma short int no? Mi riferisco alla seguente domanda su questo sito: C# compiler number literalsPerché alcuni tipi non hanno modificatori letterali

In generale, C# sembra essere un linguaggio molto ben progettato e coerente. Probabilmente c'è una forte ragione per fornire modificatori letterali per alcuni tipi, ma non per tutti. Che cos'è?

+1

Dai un'occhiata a questa domanda (e la risposta di Eric Lippert): http://stackoverflow.com/questions/1678591/why-are-number-suffixes-necessable –

risposta

35

Perché long int ha un modificatore letterale, ma breve int no?

La domanda è "perché C# non ha questa funzione?" La risposta a questa domanda è sempre la stessa. Le funzionalità non sono implementate per impostazione predefinita; C# non ha questa caratteristica perché nessuno ha progettato, implementato e spedito la funzionalità ai clienti.

L'assenza di una funzione non ha bisogno di giustificazione. Piuttosto, tutte le caratteristiche devono essere giustificate dimostrando che i loro benefici superano i loro costi. Come la persona che propone la funzione, l'onere è su di te per descrivere perché pensi che la funzione sia preziosa; l'onere non è su di me per spiegare perché non lo è.

Probabilmente esiste un motivo valido per fornire i modificatori letterali per alcuni tipi, ma non per tutti. Che cos'è?

Ora questa è una domanda più comprensibile. Ora la domanda è "cosa giustifica il suffisso letterale a lungo, e perché non è anche una giustificazione per un suffisso letterale simile in breve?"

I numeri interi possono essere utilizzati per una varietà di scopi. Puoi usarli come numeri aritmetici . Puoi utilizzarli come raccolte di bit bit. Puoi usarli come indici negli array. E ci sono molti altri usi speciali. Ma penso sia giusto dire che la maggior parte delle volte, gli interi sono usati come numeri aritmetici.

La stragrande maggioranza dei calcoli eseguiti in interi da programmi normali coinvolge numeri che sono molto, molto più piccoli del range di un intero con segno a 32 bit - circa +/- 2 miliardi. E un sacco di hardware moderno è estremamente efficiente quando si tratta esclusivamente di interi a 32 bit. Ha quindi senso rendere la rappresentazione predefinita dei numeri da firmare interi a 32 bit. C# è quindi progettato per fare calcoli che coinvolgono interi con segno a 32 bit sembrano perfettamente normali; quando dici "x = x + 1" che "1" è un intero con segno a 32 bit, e le probabilità sono buone anche x e il risultato della somma è troppo.

Cosa succede se il calcolo è integrale ma non si adatta all'intervallo di un numero intero a 32 bit?gli interi "lunghi" a 64 bit sono un sensibile passo successivo; sono anche efficienti su un sacco di hardware e hanno una gamma che dovrebbe soddisfare le esigenze di quasi tutti coloro che non stanno facendo combinatori heavy-duty che coinvolgono numeri estremamente grandi. Ha quindi senso avere un modo per specificare in modo chiaro e conciso nel codice sorgente che questo letterale qui deve essere trattato come un intero lungo.

Gli scenari di interoperabilità o gli scenari in cui gli interi vengono utilizzati come campi bit, richiedono spesso l'uso di numeri interi non firmati. Di nuovo, ha senso avere un modo per specificare in modo chiaro e conciso che questo letterale è destinato a essere trattato come un intero senza segno.

Quindi, riassumendo, quando vedi "1", le probabilità sono buone che la maggior parte delle volte l'utente intende utilizzarlo come un intero con segno a 32 bit. Il prossimo caso più probabile è che l'utente intenda che sia un intero lungo o un intero senza segno o senza firma. Pertanto ci sono suffissi concisi per ciascuno di questi casi.

Pertanto, la funzione è giustificata.

Perché non è una giustificazione per i cortometraggi?

Perché innanzitutto, in ogni contesto in cui un cortocircuito è legale, è già legale utilizzare un numero intero letterale. "short x = 1;" è perfettamente legale; il compilatore comprende che l'intero si inserisce in un breve e ti consente di usarlo.

Secondo, l'aritmetica non viene mai eseguita in corti in C#. L'aritmetica può essere eseguita in interi, uints, long e long, ma l'aritmetica è mai fatta in corti. Gli short promuovono a int e l'aritmetica è fatta in pollici, perché come ho detto prima, lo la stragrande maggioranza dei calcoli aritmetici si adattano a un int. La stragrande maggioranza è non in forma in un breve. L'aritmetica breve è probabilmente più lenta su hardware moderno che è ottimizzato per gli interi, e l'aritmetica breve non occupa meno spazio; sarà fatto in pollici o long sul chip.

Si desidera un suffisso "lungo" per indicare al compilatore "questa aritmetica deve essere eseguita a lungo" ma un suffisso "breve" non dice al compilatore "questa aritmetica deve essere eseguita in cortocircuito" perché è semplicemente non una caratteristica del linguaggio C# per cominciare.

I motivi per fornire un suffisso lungo e una sintassi non firmata non si applicano ai cortocircuiti. Se ritieni che vi sia un vantaggio convincente per la funzionalità, specifica quali sono i vantaggi. Senza un vantaggio per giustificare i suoi costi, la funzionalità non sarà implementata in C#.

+1

dovrebbe essere una giustificazione abbastanza forte, non dovrebbe? Tuttavia, questa incoerenza sembra essere lì per un motivo: mi mette in guardia dai costi di conversione a int e ritorno a breve ogni volta che ho bisogno di fare qualcosa con il mio corto. –

+0

@Lund: non vi è alcun costo associato alla conversione, a meno che non si utilizzi l'aritmetica controllata. L'aritmetica viene eseguita nei registri della CPU che sono sempre larghi almeno 32 bit. Le istruzioni di caricamento della memoria e di memorizzazione eseguono correttamente le conversioni e possono variare leggermente nel conteggio dei cicli. Tuttavia, l'utilizzo della cache di beter spesso compensa più di qualsiasi perdita, potenzialmente rendendo le prestazioni complessive utilizzando cortometraggi migliori rispetto all'utilizzo di ints. –

+3

@KevinCathcart: a condizione che i pantaloncini siano ben stretti. Una serie di cortocircuiti, ad esempio, potrebbe comportare un minor numero di errori di cache rispetto a un array di int. Ma spesso vedo le persone che dichiarano * le variabili locali * come corte perché pensano che farlo sia "salvare due byte di memoria", che è una sciocchezza. –

1

Se si dichiara un corto letterale e lo si ingrandisce di Short.MaxValue, si verificherà un errore del compilatore, altrimenti il ​​valore letterale sarà breve.

+1

Un letterale può essere lungo, ad esempio 1L. Apparentemente non esiste un letterale breve. –

+1

@BasB: Questo non è del tutto corretto: puoi dichiarare una variabile o una costante che è 'short', ma devi inizializzarla con un letterale non breve; il controllo dell'intervallo viene eseguito, come si nota, dal compilatore. La specifica C# (4.0) definisce i letterali nella sezione 2.4.4 e, dei letterali interi, dice che "sono usati per scrivere valori di tipi' int', 'uint',' lungo' e 'ulong'." – phoog

2

Da un short può essere implicitamente convertito int, long, float, double o decimal; non c'è bisogno di un modificatore letterale.

considerare:

void method(int a) {} 
void method2() 
{ 
    short a = 4; 
    method(a); // no problems 
} 

Si può notare che char e byte sono anche con modificatori letterali, per forse questo stesso motivo.

From To 
sbyte short, int, long, float, double, or decimal 
byte short, ushort, int, uint, long, ulong, float, double, or decimal 
short int, long, float, double, or decimal 
ushort int, uint, long, ulong, float, double, or decimal 
int  long, float, double, or decimal 
uint long, ulong, float, double, or decimal 
long float, double, or decimal 
char ushort, int, uint, long, ulong, float, double, or decimal 
float double 
ulong float, double, or decimal 
+4

Il tuo metodo2 ha dimostrato la conversione 'short' =>' int', questa è l'altra direzione rispetto a 'short s = 1;' –

9

Secondo MSDN:

short x = 32767; 

Nella dichiarazione precedente, l'intero letterale 32767 è implicitamente convertito da int a breve. Se il valore letterale intero non si adatta a una posizione di memoria breve, si verificherà un errore di compilazione.

Quindi è una funzione di compilazione. short non ha un suffisso perché non sarebbe mai necessario.

La domanda correlata è probabilmente: Perché long, float e decimal hanno suffissi?
E una risposta breve sarebbe che i + 1 e i + 1L possono produrre valori diversi e sono quindi di tipi diversi.

Tuttavia, non esiste una "aritmetica breve", i valori short vengono sempre convertiti in int quando vengono utilizzati in un calcolo.

+0

Henk, mi è piaciuto scrivere. È un peccato che non accetti due risposte. –

4

Come Eric sottolinea nel commento, la mia risposta di seguito non ha senso. Penso che sia più corretto dire che l'incapacità di esprimere un breve letterale in C# e l'incapacità di esprimere un breve letterale in IL condividono una causa comune (la mancanza di un motivo convincente per la caratteristica). Apparentemente VB.Net ha un breve specificatore letterale, che è interessante (per la retrocompatibilità con la sintassi VB?) In ogni caso, ho lasciato qui la risposta in quanto alcune informazioni potrebbero essere interessanti, anche se il ragionamento è scorretto.


Non v'è alcun breve letterale perché non c'è in realtà un modo per un breve letterale per essere caricati in IL, il linguaggio di base utilizzato dal CLR. Questo perché tutti i tipi 'short' (qualsiasi cosa più piccola di un int) vengono implicitamente allargati a un int quando caricati nello stack delle operazioni. Firmati e non firmati sono allo stesso modo una questione di operazioni e non effettivamente "memorizzati" con il numero attivo nella pila delle operazioni.I tipi "corti" entrano in gioco solo quando si desidera memorizzare un numero sullo stack delle operazioni in una posizione di memoria, quindi ci sono operazioni IL da convertire in vari tipi "brevi" (sebbene in realtà rimandi ancora il numero a un int dopo la conversione, fa semplicemente in modo che il valore sia adatto per la memorizzazione in un campo di tipo "corto".)

I tipi lunghi hanno uno specificatore letterale, d'altra parte, perché sono trattato diversamente sullo stack operativo. Esiste un'istruzione Ldc_I8 separata per caricare valori lunghi costanti. Ci sono anche Ldc_R4 (quindi perché hai bisogno di "f" per float) e Ldc_R8 (C# sceglie questo come predefinito se usi un numero decimale senza un identificatore.) Il decimale è un caso speciale, in quanto non è in realtà un tipo primitivo in IL ; ha solo un identificatore costante incorporato 'm' in C# che compila in una chiamata del costruttore.

Per quanto riguarda il motivo per cui non ci sono operazioni brevi speciali (e corrispondenti brevi letterali), è probabile perché la maggior parte delle architetture CPU attuali non funzionano con registri più piccoli di 32 bit, quindi non c'è distinzione a livello di CPU che valga la pena sfruttare. Potresti potenzialmente salvare la dimensione del codice (in termini di byte di IL) consentendo il "breve" caricamento degli opcode IL, ma al costo di una complessità aggiuntiva per il jitter; lo spazio del codice salvato probabilmente non ne vale la pena.

+0

("potresti potenzialmente salvare la dimensione del codice ...") - Ma ci * sono * opcodes "brevi", per il salvataggio di byte di IL (che significa che il codice CIL è breve, non necessariamente che riguardano il tipo di dati 'short'). Ad esempio, esiste persino uno per i4 (quattro byte int): 'ldc.i4.s' prende un argomento di un byte e inserisce quel valore nello stack come int32. Dalla specifica: "Esistono codifiche speciali per i numeri interi da -128 a 127 (con codifiche particolarmente brevi da -1 a 8)." – phoog

+4

Questa risposta non ha alcun senso. L'errore fondamentale è nella prima frase. Se il motivo per cui la caratteristica non è in C# è perché C# si compila in IL, allora perché è la funzione in altri linguaggi che compila in IL? La consistenza –

0

L'ora in cui ho "lavorato in Corto" era per i valori memorizzati in un database.

Sono valori interi positivi che raramente passano da 10 a 20. (un byte o sbyte sarebbe abbastanza grande, ma ho pensato che un po 'di over kill mi avrebbe impedito di rimpiangere la mia scelta, se il codice fosse riutilizzato in un leggermente diverso)

Il campo viene utilizzato per consentire all'utente di ordinare i record in una tabella. Questa tabella alimenta un elenco a discesa o un pulsante di opzione ordinato per "ora" (passaggio uno, passaggio due, ...).

Essendo nuovo in C# (e abbastanza vecchio da ricordare quando il conteggio dei byte era importante) ho pensato che sarebbe stato un po 'più efficiente. Non faccio matematica sui valori. Ho solo ordinarli (e scambiarli tra i record). L'unica matematica finora è stata "MaxInUse" +1 (per i nuovi record), che è un caso speciale "++ MaxInUse".Questo è buono, perché la mancanza di un letterale significa "s = s + 2" dovrebbe essere "s = (Int16) (s + 2)".

Ora che vedo come C# fastidioso funziona con gli altri inte, mi aspetto di unire il mondo moderno e sprecare byte, JUST per rendere felice il compilatore.

Ma, non dovrebbe "rendere il compilatore felice" il punteggio # 65 nei nostri 10 principali obiettivi di programmazione?

È MAI un vantaggio avere il compilatore lamentarsi dell'aggiunta del numero intero "2" a QUALSIASI dei tipi di INTEGER? Dovrebbe lamentarsi di "s = 123456", ma questo è un caso diverso.

Se qualcuno ha a che fare con matematica e pantaloncini, suggerisco di creare i propri letterali. (Quanti potrebbe hai bisogno?)

short s1= 1, s2 = 2, s123 = 123; 

Poi s = s + S2 è solo un po 'fastidioso (e fonte di confusione per coloro che seguono dopo).

+0

Ho pensato, dovrei provare, invece di far saltare una buona idea. s = s + s2; Dà lo stesso errore di s = s + 2. Il compilatore C# è così fastidioso da essere fortemente digitato, un breve + un corto produce un Int. Questo potrebbe essere il motivo per cui diverse persone hanno affermato che tutta la matematica è fatta come Ints. Sulla base di questo test, propongo una risposta alla domanda originale. Un letterale breve non esiste, perché non sarebbe mai utile. Anche se ne hai avuto uno, non puoi aggiungere 2 corti e metterlo in un altro corto. (Questo mi riporta indietro in un cerchio per chiedere a WHY. Ma, questo è per un altro giorno.) –

Problemi correlati