Quando si aggiunge uno int32
a un native int
a 64 bit, il CLR sign-estendere o estendere a zero il numero intero a 32 bit? E soprattutto: sulla base di quali informazioni fa questa scelta?Risultato dell'aggiunta di un int32 a un nativo a 64 bit int?
Sto scrivendo un compilatore .NET e hanno letto la specifica ECMA accuratamente, ma non riusciva a trovare una risposta.
La CLI supporta solo un sottoinsieme di questi tipi nelle sue operazioni su valori memorizzati sul suo stack di valutazione:
int32
,int64
enative int
.
- ECMA 335, Sezione I 12.1: supportati i tipi di dati
Poiché i valori nello stack di valutazione non hanno informazioni sulla loro signedness, istruzioni per i quali il signedness degli operandi importa avere due varianti: una per firmato e uno per interi senza segno. Le istruzioni add
, sub
e mul
(quelle che non controllano l'overflow) non devono preoccuparsi della firma degli operandi purché gli operandi abbiano le stesse dimensioni e pertanto abbiano solo una singola variante. Tuttavia, gli operandi non sono sempre le stesse dimensioni ...
ECMA 335, Sezione III 1.5: Operando tipo di tabella si rileva che una int32
e native int
può essere aggiunto, sottratto, moltiplicato e diviso. Il risultato è ancora un native int
. Su un sistema a 64 bit, uno native int
ha una larghezza di 64 bit.
ldc.i4.0 // Load int32 0
conv.i // Convert to (64-bit) native int
ldc.i4.m1 // Load int32 -1
add // Add native int 0 and int32 0xFFFFFFFF together
Quindi quale sarebbe il risultato qui? Si noti che, in base alle specifiche, il runtime non deve tracciare i tipi esatti o la firma dei valori nello stack: conosce solo int32
, int64
e native int
(e alcuni altri che non sono rilevanti qui).
Immagino che IntPtr
e UIntPtr
aritmetica, dal momento che è rappresentato internamente come interi nativi, potrebbe anche utilizzare questo tipo di aggiunta. Tuttavia, ILSpy mostra che l'aggiunta di uno IntPtr
e uno Int32
in C# chiama l'operatore + sovraccarico sulla classe IntPtr
, che accetta solo un argomento firmato Int32
.
Facendolo direttamente in CIL (utilizzando l'istruzione add
) indica anche che il numero intero viene interpretato come firmato. Dovrebbe anche essere stato implementato in Mono, ma non sono riuscito a trovare alcun riferimento per le mie scoperte.
Il segno per il valore promosso non verrà catturato. Vedi queste informazioni per possibili soluzioni (è per Mac ma ciò non dovrebbe importare in questo caso): https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/64bitPorting/MakingCode64-BitClean/MakingCode64- BitClean.html – K3N