Mengapa unsigned int dari bit-field menjadi int bertanda tangan setelah operasi shift di C ++? [duplikat]

Dec 15 2020

Kode tes:

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;
}

Outputnya adalah:, -65536dan jenisnya badalah inttetapi tidak uint32_t.

Saya telah menemukan itu, uint16_tdan uint8_tjuga akan menjadi ditandatangani int setelah operator shift, dan ada pertanyaan serupa di C#, yang sampai pada kesimpulan bahwa hasilnya akan menjadi ditandatangani ketika operan <32 bit. Mengapa operasi shift selalu menghasilkan int yang ditandatangani ketika operan <32 bit

Tapi jenisnya a.lojelas uint32_t, yang bisa dibuktikan kebenarannya decltype(a.lo), lalu bagaimana menjelaskannya?

Jawaban

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

Itu bagian dari promosi integral standar.

[expr.shift]

1 Operator shift <<dan >>grup dari kiri ke kanan

Operand harus dari tipe enumerasi integral atau tanpa cakupan dan promosi integral dilakukan. Jenis hasilnya adalah operan kiri yang dipromosikan.

[konv.prom]

5 Sebuah prvalue untuk integral bit-field ([class.bit]) dapat diubah menjadi prvalue tipe intjika intdapat mewakili semua nilai dari bit-field; jika tidak, dapat diubah menjadi unsigned intjika unsigned intdapat mewakili semua nilai bidang bit. Jika bit-field lebih besar lagi, tidak ada promosi integral yang berlaku untuk itu. Jika bit-field memiliki tipe yang disebutkan, itu diperlakukan sebagai nilai lain dari tipe itu untuk tujuan promosi.

Promosi operan kiri Anda (bit-field) menghasilkan int, dan itulah jenis ekspresi keseluruhan shift. Dengan demikian badalah intjuga dengan jenis placeholder deduksi.