C ++ 'da vardiya işleminden sonra işaretsiz bir bit alanı int'i neden işaretli bir int olur? [çiftleme]
Test kodu:
struct A
{
uint32_t lo : 16;
uint32_t hi : 16;
};
int main()
{
A a{};
a.lo = 0xFFFF;
auto b = a.lo << 16;
cout << b << endl;
return 0;
}
Çıktı şöyledir: -65536
ve tipi b
olduğunu int
fakat uint32_t
.
Bunu buldum uint16_t
ve uint8_t
ayrıca vardiya operatöründen sonra int C#
imzalı hale geleceğim ve işlenen <32 bit olduğunda sonucun imzalanacağı sonucuna varan benzer bir soru vardı . Neden vardiya işlemleri her zaman işlenen <32 bit olduğunda işaretli bir int ile sonuçlanır?
Ama türü a.lo
açıkça uint32_t
doğrulanabilir decltype(a.lo)
, peki bu nasıl açıklanabilir?
Yanıtlar
Standart entegre promosyonun bir parçasıdır.
[ifade kaydırma]
1 Vardiya operatörleri
<<
ve>>
grup soldan sağaİşlenenler, integral veya kapsamsız numaralandırma tipinde olacaktır ve integral yükseltmeler gerçekleştirilir. Sonucun türü, yükseltilmiş sol işlenenin türüdür.
[dönş.prom]
5 ayrılmaz bir bit alanı ([class.bit]) için bir prvalue tipte bir prvalue dönüştürülebilir
int
eğerint
bit alanının tüm değerleri temsil edebilir; aksi takdirde dönüştürülebilirunsigned int
eğerunsigned int
bit alanın tüm değerleri temsil edebilir. Bit alanı henüz daha büyükse, ona hiçbir integral yükseltme uygulanmaz. Bit alanının numaralandırılmış bir türü varsa, yükseltme amaçları için bu türden herhangi bir değer olarak değerlendirilir.
Sol operandınızın (bit alanı) terfisi bir üretir int
ve bu nedenle tüm shift ifadesinin türü budur. Bu nedenle b
, int
yer tutucu türden bir kesinti.