Perché un breve deve essere convertito in un int prima delle operazioni aritmetiche in C e C ++?

Dalle risposte che ho ottenuto da questa domanda , sembra che C ++ abbia ereditato questo requisito per la conversione di short in int quando si eseguono operazioni aritmetiche da C. Posso scegliere il motivo per cui questo è stato introdotto in C, in primo luogo? Perché non fare queste operazioni in short ?

Ad esempio ( tratto dal suggerimento di dyp nei commenti ):

 short s = 1, t = 2 ; auto x = s + t ; 

x avrà tipo di int .

    Se consideriamo la logica per i linguaggi di programmazione standard internazionali-C nella sezione 6.3.1.8 Conversioni aritmetiche usuali dice ( enfatizza il mio futuro ):

    Le regole dello standard per queste conversioni sono lievi modifiche di quelle in K & R: le modifiche accolgono i tipi aggiunti e le regole di conservazione del valore. È stata aggiunta una licenza esplicita per eseguire calcoli in un tipo “più ampio” di quanto assolutamente necessario, poiché a volte questo può produrre codice più piccolo e più veloce, per non parlare della risposta corretta più spesso . I calcoli possono anche essere eseguiti in un tipo “più stretto” dalla regola come se fintanto che si ottiene lo stesso risultato finale. Il casting esplicito può sempre essere utilizzato per ottenere un valore in un tipo desiderato

    La sezione 6.3.1.8 della bozza dello standard C99 copre le conversioni aritmetiche usuali applicate agli operandi di espressioni aritmetiche, ad esempio la sezione 6.5.6 operatori additivi dicono:

    Se entrambi gli operandi hanno un tipo aritmetico, vengono eseguite le normali conversioni aritmetiche .

    Troviamo testo simile nella sezione 6.5.5 Operatori moltiplicativi . Nel caso di un operando breve , prima vengono applicate le promozioni intere dalla sezione 6.3.1.1 Booleano, caratteri e numeri interi che dice:

    Se un int può rappresentare tutti i valori del tipo originale, il valore viene convertito in un int; in caso contrario, viene convertito in un int unsigned. Queste sono chiamate promozioni intere . 48) Tutti gli altri tipi sono invariati dalle promozioni intere.

    La discussione della sezione 6.3.1.1 della Razionale o dei linguaggi di programmazione internazionale standard-C sulle promozioni intere è in realtà più interessante, ho intenzione di quotare selettivamente b / c è troppo lunga per citare pienamente:

    Le implementazioni caddero in due campi principali che potrebbero essere caratterizzati come conservazione non firmata e conservazione del valore .

    […]

    L’ approccio di conservazione non firmato richiede la promozione dei due tipi di unsigned più piccoli a unsigned int. Questa è una regola semplice e produce un tipo che è indipendente dall’ambiente di esecuzione.

    L’ approccio di preservazione del valore richiede la promozione di quei tipi a int firmato se quel tipo può rappresentare correttamente tutti i valori del tipo originale e in caso contrario per promuovere tali tipi a int unsigned. Quindi, se l’ambiente di esecuzione rappresenta breve come qualcosa di più piccolo di int, il corto senza segno diventa int; altrimenti diventa int unsigned.

    Ciò può avere alcuni risultati piuttosto inaspettati in alcuni casi come dimostra un comportamento incoerente di conversione implicita tra tipi di firma non firmati e più grandi , ci sono molti altri esempi come questo. Anche se nella maggior parte dei casi ciò comporta che le operazioni funzionino come previsto.

    Non è una caratteristica del linguaggio tanto quanto è una limitazione delle architetture dei processori fisici su cui viene eseguito il codice. L’ int tper di C è solitamente la dimensione del registro CPU standard. Più silicio occupa più spazio e più potenza, quindi in molti casi l’aritmetica può essere eseguita solo sui tipi di dati “di dimensioni naturali”. Questo non è universalmente vero, ma la maggior parte delle architetture ha ancora questa limitazione. In altre parole, quando si aggiungono due numeri a 8 bit, ciò che effettivamente accade nel processore è un tipo di aritmetica a 32 bit seguita da una semplice maschera bit o un’altra conversione di tipo appropriato.

    float tipi float , short e char sono considerati dal tipo standard di “tipi di storage”, ovvero sotto-intervalli che puoi usare per risparmiare spazio ma che non ti compreranno alcuna velocità perché la loro dimensione è “innaturale” per la CPU.

    Su alcune CPU questo non è vero, ma i buoni compilatori sono abbastanza intelligenti da notare che se si aggiunge una costante ad un carattere non firmato e si memorizza il risultato in un carattere non firmato, non è necessario passare alla conversione unsigned char -> int . Ad esempio con g ++ il codice generato per il ciclo interno di

     void incbuf(unsigned char *buf, int size) { for (int i=0; i 

    è solo

     .L3: addb $1, (%rdi,%rax) addq $1, %rax cmpl %eax, %esi jg .L3 .L1: 

    dove puoi vedere che viene utilizzata un'istruzione di aggiunta di char senza firma ( addb ).

    Lo stesso accade se stai facendo i tuoi calcoli tra brevi intervalli e memorizzando il risultato a breve.

    La domanda collegata sembra coprire abbastanza bene: la CPU non lo fa. Una CPU a 32 bit ha le operazioni aritmetiche native impostate per i registri a 32 bit. Il processore preferisce lavorare nella sua dimensione preferita, e per operazioni come questa, copiare un piccolo valore in un registro di dimensioni native è economico. (Per l’architettura x86, i registri a 32 bit vengono denominati come se fossero versioni estese dei registri a 16 bit (da eax a ax , ebx a bx , ecc.), Consultare le istruzioni di x86 integer ).

    Per alcune operazioni estremamente comuni, in particolare l’aritmetica vettoriale / mobile, possono esserci istruzioni specializzate che operano su un tipo o una dimensione di registro differente. Per qualcosa di simile a un corto, il riempimento con (fino a) 16 bit di zeri ha un costo molto basso delle prestazioni e l’aggiunta di istruzioni specializzate probabilmente non vale il tempo o lo spazio sul dado (se vuoi essere veramente fisica sul perché; non sono sicuro che prenderebbero lo spazio reale, ma diventerebbe molto più complesso).