Son zamanlarda bazı eski kodlarda garip davranışlar keşfettik. Bu kod çağlar için çalıştı, ancak bazı platformlarda (XBox 360, PowerPC) derleyici optimizasyonları maksimuma çıkarıldı. Genellikle, tanımlanmamış davranışlardan şüphelenirim.Uygun bir derleyici uint32_t -> int16_t -> int32_t dönüşümü yapabilir mi?
Kod böyle kabaca görünür:
#include <stdint.h>
uint32_t sign_extend16(uint32_t val)
{
return (int32_t)(int16_t)val;
}
Söz konusu operasyon çok garip olmamalı böylece bir emülatör bir parçası. Normal olarak, bunun yalnızca 16 bitlik değerleri dikkate almasını ve bunu 32 bit'e kadar uzatmasını beklerim. Görünüşe göre, bu yaş için sahip olduğu davranıştı. onunla işaretsiz birinin değerini temsil etmek mümkün olmamalıdır
0000000000000000 <sign_extend16>:
0: 0f bf c7 movswl %di,%eax
3: c3 retq
Ancak, ben bir tanımlanmamıştır imzalı imzasız bir dönüştürme, standardın anlayabileceği kadarıyla: x86_64 günü, GCC bana bu sonucu verir imzalı tip.
Daha sonra başka bir değerin tanımsız olacağı için, derleyicinin imzasız değerin [0, 32767]
aralığında olması gerektiğini varsayması mümkün olabilir mi? Bu durumda, int16_t
'a bir döküm ve yine int32_t
'a başka bir oyuncu hiçbir şey yapmaz. Bu durumda, derleyicinin kodu basit bir harekete çevirmesi yasal olabilir mi?
'(int16_t) val'ın davranışı asla tanımsız değildir. Davranış, 'val' bir int16_t 'olarak gösterilebiliyorsa, davranış tanımsal olarak tanımlanmışsa iyi tanımlanır. –
@Maister, x86_64'te tam olarak sorun nedir? movswl talimatı uzatma imzaladı. 32768 değerini geçtiğinizde elde ettiğiniz sonuç nedir? "Gcc" ile 32 bit/64 bit sistemlerde, dönüş değeri 0xFFFF8000 olmalıdır. – ouah
Yeterince açık olmayabilirdim. X86_64 üzerinde davranış beklenmektedir. Ancak xbox 360'da beklendiği gibi davranmaz. – Maister