Domanda

Considera il seguente codice:

void f(byte x) {print("byte");}
void f(short x) {print("short");}
void f(int x) {print("int");}

void main() {
    byte b1, b2;
    short s1, s2;

    f(b1 + b2); // byte + byte = int
    f(s1 + s2); // short + short = int
}

In C ++, C #, D e Java, entrambe le chiamate di funzione si risolvono in " int " sovraccarichi ... Capisco già questo è " nelle specifiche " ;, ma perché le lingue sono progettate in questo modo? Sto cercando un motivo più profondo.

Per me ha senso che il risultato sia il tipo più piccolo in grado di rappresentare tutti i possibili valori di entrambi gli operandi , ad esempio:

byte + byte --> byte
sbyte + sbyte --> sbyte
byte + sbyte --> short
short + short --> short
ushort + ushort --> ushort
short + ushort --> int
// etc...

Ciò eliminerebbe il codice scomodo come short s3 = (short) (s1 + s2) , così come l'IMO sarebbe molto più intuitivo e più facile da capire.

È un'eredità lasciata dai tempi di C o ci sono ragioni migliori per l'attuale comportamento?

È stato utile?

Soluzione

Citato da questo post sul blog MSDN :

  

byte b = 32; byte c = 240; int i = b +   c; // cosa sono io?

     

In questo mondo fantastico, il valore di i   sarebbe 16! Perché? Perché i due   gli operandi per l'operatore + sono entrambi   byte, quindi la somma "b + c" è calcolato come   un byte, che risulta in 16 a causa di   overflow intero. (E, come ho notato   in precedenza, l'overflow dei numeri interi è il nuovo   vettore di attacco di sicurezza.)

     

Allo stesso modo,

     

int j = -b;

     

comporterebbe j con il valore 224   e non -32, per lo stesso motivo.

     

È davvero quello che vuoi?

     

...

     

Quindi, non importa come lo tagli, lo sei   dovrà inserire fastidiosi   getta. Può anche avere la lingua   err dal lato della sicurezza (costringendoti   per inserire i calchi dove conosci   che l'overflow non è un problema) rispetto a   errare dal lato del silenzio (dove tu   potrebbe non notare i cast mancanti fino al   il tuo reparto buste paga ti chiede perché   i loro libri non si sommano alla fine di   il mese).

Inoltre, vale la pena notare che aggiungere in questi cast significa solo digitare in più e niente di più. Una volta che JIT (o forse il compilatore statico stesso) riduce l'operazione aritmetica a un'istruzione di base del processore, non c'è nulla di intelligente in corso - è solo se il numero viene trattato come un int o byte .

Questa è una buona domanda, tuttavia ... per niente ovvia. Spero che ora le ragioni siano chiare per te.

Altri suggerimenti

Un migliore insieme di regole IMHO, se si prevedesse che gli operatori di spostamento potrebbero essere utilizzati solo con valori di spostamento costanti (utilizzare le funzioni di spostamento per importi di spostamento variabili), sarebbe che i risultati di qualsiasi espressione aritmetica dovrebbero sempre valutare come se sono stati elaborati con il tipo di firma o non firmata più grande possibile, a condizione che uno dei due potesse essere staticamente garantito per fornire risultati corretti (si applicherebbero regole leggermente complicate nei casi in cui il tipo con firma più grande potrebbe non essere sufficiente). A condizione che gli operandi a turni possano essere solo costanti, si potrebbe determinare abbastanza facilmente in fase di compilazione quale potrebbe essere il valore più significativo di qualsiasi operando, quindi non vedo alcuna buona ragione per i compilatori di non vedere come viene utilizzato il risultato di un operatore nel decidere sull'attuazione dell'operatore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top