C ++ 'da vardiya işleminden sonra işaretsiz bir bit alanı int'i neden işaretli bir int olur? [çiftleme]

Dec 15 2020

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: -65536ve tipi bolduğunu intfakat uint32_t.

Bunu buldum uint16_tve uint8_tayrı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.loaçıkça uint32_tdoğrulanabilir decltype(a.lo), peki bu nasıl açıklanabilir?

Yanıtlar

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

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 inteğer intbit alanının tüm değerleri temsil edebilir; aksi takdirde dönüştürülebilir unsigned inteğer unsigned intbit 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 intve bu nedenle tüm shift ifadesinin türü budur. Bu nedenle b, intyer tutucu türden bir kesinti.