Dodając int32
do 64 bitów native int
, czy CLR logowania rozszerzyć lub zerowej przedłużenie 32-bitową liczbę całkowitą? A co najważniejsze: na podstawie jakich informacji dokonuje tego wyboru?Wynik dodania int32 do 64-bitowego natywnego int?
Piszę kompilatora .NET i przeczytałem specyfikacji ECMA throughly, ale nie mógł znaleźć odpowiedź.
CLI obsługuje tylko podzbiór tych typów w jego operacji na wartościach zapisanych na stosie ocena:
int32
,int64
inative int
.
- ECMA 335 sekcja I 12.1: Obsługiwane typy danych
Ponieważ wartości na stosie oceny nie mają informacji na temat ich signedness, instrukcje dla którego uzyskiwany znak argumentów liczą mieć dwa warianty: jeden dla podpisany i jeden dla liczb całkowitych bez znaku. W add
, sub
i mul
instrukcje (te, które nie sprawdzają przepełnienia) nie muszą się martwić o uzyskiwany znak argumentów tak długo jak operandy są tej samej wielkości, a zatem mają tylko jeden wariant. Jednak argumenty nie zawsze są tej samej wielkości ...
ECMA 335 sekcja III 1.5: Argument typu tabela stwierdza, że int32
i native int
można dodać, odjąć, mnoży i dzieli. Rezultatem jest ponownie native int
. W systemie 64-bitowym numer native int
ma szerokość 64 bitów.
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
Jaki byłby rezultat? Należy zauważyć, że zgodnie ze specyfikacją, środowisko wykonawcze nie musi śledzić dokładnych typów lub uzyskiwany znak wartości na stosie: wie tylko int32
, int64
i native int
(i kilka innych, które nie są istotne tutaj).
Mogę sobie wyobrazić, że IntPtr
i UIntPtr
arytmetyka, ponieważ jest wewnętrznie reprezentowane rodzimych wskazówki, również korzysta z tego rodzaju dodatek. Jednak ILSpy pokazuje, że dodanie IntPtr
oraz Int32
w C# wywołuje przeciążony operator + na klasie IntPtr
, który akceptuje tylko podpisane Int32
argument.
Wykonanie tego bezpośrednio w CIL (przy użyciu instrukcji add
) wskazuje również, że liczba całkowita jest interpretowana jako podpisana. Powinien również zostać zaimplementowany w Mono, ale nie mogłem znaleźć żadnych odniesień do poparcia moich odkryć.
Znak promowanej wartości nie zostanie przechwycony. Zobacz te informacje o możliwych rozwiązaniach (dotyczy to komputerów Mac, ale nie powinno to mieć znaczenia w tym przypadku): https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/64bitPorting/MakingCode64-BitClean/MakingCode64- BitClean.html – K3N