Bitfaylga maksimal qiymatni belgilash uchun ko'chma usul

Bunga o'xshash bir gap bor:

struct SomeStruct {
    uint32_t first : 12;
    uint32_t second : 2;
    uint32_t third : 18;
};

SomeStruct obj;

Men tayinlashni xohlayman

obj.second = 3; //Actually, the maximum allowed value

Bunga erishishning ko'chma yo'li nima? Bundan tashqari, ma'lum bir bit maydon kengligini aniq ishlatmoqchi emasmiz.

Mening kodim ishlatilgan

obj.second = std::numeric_limits::max()

but clang with -Wbitfield-constant-conversion gives a warning about it and cpp reference states:

Bit maydonlarining quyidagi xususiyatlari quyidagicha bajariladi: The   bir bit maydonni tayinlash yoki ishga tushirishdan kelib chiqadigan qiymat   qiymat oralig'idan tashqarida yoki bir xil maydonni oraliq oralig'idan oshirgan holda.

So is assigning -1 or numeric_limits::max() actually portable or is there any other way?

0
@NathanOliver, shuning uchun mening savolimga javob berish "bu imkonsiz" deb aytasizmi?
qo'shib qo'ydi muallif unkulunkulu, manba
Men maksimal qiymatni belgilashni xohlayman. Bog'langan savollar avval bitni o'lchash yo'li bilan bajarish mumkin emasligini bildiradi. Qizig'i shundaki, bit hajmini olish maksimal qiymatni olish orqali amalga oshirilishi mumkin :)
qo'shib qo'ydi muallif unkulunkulu, manba
qo'shib qo'ydi muallif NathanOliver, manba
Yaxshi, agar siz maksimalni hisoblash uchun bit bilan o'lchamni olishni xohlasangiz, ha. Bu siz xohlagan narsaga bog'liq. Shuning uchun birinchi navbatda men bilan suhbatlashdim.
qo'shib qo'ydi muallif NathanOliver, manba

5 javoblar

Maydonlarni imzolamaganligi uchun ish oson:

obj.second = -1;

Tasdiqlanmagan arifmetik bitfayllar uchun ham aylanadi.

2
qo'shib qo'ydi
Bu maqbul javob
qo'shib qo'ydi muallif Angus Comber, manba
@unkulunkulu Men ushbu taklifga mos keladigan C ++ standartidagi hech qanday matnni ko'rmayapman. Bit-joylar bo'limida hech narsa yo'q, bu ularning tashqi o'zgaruvchan konvertatsiyasida ularning xatti-harakatlarini istisno qiladi; shuning uchun o'ylaymanki [conv.integral] qo'llaniladi, bu boshqa tamsayılar uchun ham xuddi shunday xatti-harakatlardir: atrofdagilarning imzo chekkasidagi sarlavhalar orasidan chetga o'tishni o'zgartirishi va imzolangan bo'lmagan tashqi almashinuvni amalga oshirish belgilanadi.
qo'shib qo'ydi muallif M.M, manba
@NathanOliver ha, bu kodda biz imzolamagan bitfayllarni qo'llamasligimiz kerak
qo'shib qo'ydi muallif M.M, manba
Men ushbu standartni/boshqa ishonchli manbaga ulanish bilan biroz ko'proq ma'lumotga ega bo'larmidingiz, shuning uchun men bu ma'lumotni topa oldim. en.cppreference.com/w/cpp/language/bit_field va u erda" Bit ob'ektlari quyidagi xususiyatlar amalga oshirish bilan aniqlanadi. Bit maydonni qiymat bilan belgilash yoki ishga tushirishdan kelib chiqadigan qiymat. yoki bir xil maydonni oralig'idan oshirib yuborishdan iborat. '
qo'shib qo'ydi muallif unkulunkulu, manba
OK, chindan ham chin dildan ogohlantirish haqida alohida savol berish va bu javobni qabul qilishim kerak. Rahmat!
qo'shib qo'ydi muallif unkulunkulu, manba
yoki haqiqatan ham bir xil savol bo'lishi mumkin. Men hozir mish-mish qilyapman. -Vbitfild-doimiy-konvertatsiya qilish bilan ishlash, bu topshiriqni bajarishga urinib, menga ogohlantirish/xatoliklarni beradi.
qo'shib qo'ydi muallif unkulunkulu, manba
Agar u maqsadli imzoni imzolagan bo'lsa, u maqsadli turdagi (va bit-kenglik kengligida) ifoda etilishi mumkin bo'lsa, qiymat o'zgarmaydi, agar ; aks holda, qiymatni amalga oshirish belgilanadi. U erda ushlab turishdan kattaroq qiymatni belgilash uchun oqilona.
qo'shib qo'ydi muallif NathanOliver, manba
@NathanOliver CWG 1816 wg21.cmeerw.net/cwg/issue1816 juda ham aniq, albatta, chegaradan tashqarida bo'lgan qiymat imzolangan va imzolangan bit-maydonlar uchun belgilangan dasturdir.
qo'shib qo'ydi muallif cmeerw, manba

Agar sizda ikki bit bo'lsa, maksimal qiymat 2 2 -1 bo'ladi. Ushbu qiymatni olishning oddiy usuli 1 chapga ikki qadam (2 2 berib) va 1dan chiqarib olishdir.

So the max value for 2 bits is (1U << 2) - 1.

Barcha S kompilyatorlari o'rtasida ko'chma bo'ladi va derleyici operatsiyani optimallashtirishi mumkin, shuning uchun topshiriq faqatgina olingan qiymat uchun bo'ladi.

2
qo'shib qo'ydi
OK, portativ rost, lekin men bu vazifani barqaror bo'lishini va bit maydonining kengligi o'zgarishi kerakligini istayman. Buni savolga qo'shaman
qo'shib qo'ydi muallif unkulunkulu, manba

CWG 1816 makes it clear that assigning a value that is not representable by the bit-field, the resulting value is implementation defined.

Qo'rqaman, siz istagan narsaga erishish uchun hech qanday portativ usulni bilmayman.

1
qo'shib qo'ydi

Tasdiqlanmagan integral turlari uchun:

unsigned char max = ~0;

Ingliz tilida noldan tashqari barcha bitlar 1 ga teng bo'lib, bu turdagi maksimal belgisiz qiymatdir.

Bitfidan foydalanayotganda, bu oddiy yondashuv siz uchun ishlamasligi mumkin. Agar siz foydalanayotgan bo'lsangiz:

struct SomeStruct {
    uint8_t first;
    uint8_t second;
    uint8_t third;
};

Keyin bu variant bo'lishi mumkin.

0
qo'shib qo'ydi
biz bitmintlarni emas, imzolangan bo'lmagan chiziqlarni ishga tushirishimiz kerak
qo'shib qo'ydi muallif M.M, manba

Buning eng yaxshi usuli -1 / -1L / ~ 0 / ~ 0L yoki INT_MAX / LONG_MAX .

Ammo bu kod, bugungi kunda kompyuterlarda tamsayılar qanday qilib namoyon bo'lishiga asoslangan. Bu har bir joyda ishlaydi, lekin rasmiy ravishda C standarti talablaridan ko'chma emas.

0
qo'shib qo'ydi
~ 0 2 ning qo'shimcha tamoyiliga asoslangan
qo'shib qo'ydi muallif M.M, manba
@ M.M .: Bu to'g'ri. Ammo kichik raqamga raqamni belgilashda C standarti modulni ishlatishini aytadi. Boshqacha qilib aytganda, agar raqam 2 kuchga ega bo'lmasa, bu g'alati raqamga olib keladi. Garchi mavjud bo'lgan dasturiy ta'minot juda ko'p bo'lsa-da ...
qo'shib qo'ydi muallif Zbynek Vyskovsky - kvr000, manba