C ++ में शिफ्ट ऑपरेशन के बाद बिट-फ़ील्ड का एक अहस्ताक्षरित int एक हस्ताक्षरित int क्यों बन जाता है? [डुप्लिकेट]

Dec 15 2020

परीक्षण कोड:

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

आउटपुट है: -65536और का प्रकार है b, intलेकिन नहीं uint32_t

मैंने पाया है कि, uint16_tऔर uint8_tशिफ्ट ऑपरेटर के बाद भी इंट्री हो जाएगी, और इसी तरह का एक प्रश्न था C#, जो इस निष्कर्ष पर पहुंचा कि जब ऑपरेंड <32 बिट्स हो तो परिणाम पर हस्ताक्षर किए जाएंगे। शिफ्ट ऑपरेशन हमेशा एक हस्ताक्षरित परिणाम में क्यों होते हैं जब ऑपरेंड <32 बिट्स होता है

लेकिन इसका प्रकार a.loस्पष्ट रूप से है uint32_t, जिसे सत्यापित किया जा सकता है decltype(a.lo), इसलिए इसे कैसे समझाया जा सकता है?

जवाब

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

यह मानक अभिन्न संवर्धन का हिस्सा है।

[expr.shift]

1 शिफ्ट ऑपरेटर <<और >>समूह बाएं से दाएं

ऑपरेंड अभिन्न या अनकैप्ड एन्यूमरेशन प्रकार के होंगे और इंटीग्रल प्रमोशन किए जाते हैं। परिणाम का प्रकार पदोन्नत बाएं ऑपरेंड है।

[conv.prom]

5 एक अभिन्न बिट क्षेत्र ([class.bit]) के लिए एक prvalue प्रकार का एक prvalue में बदला जा सकता intहै, तो intथोड़ा-क्षेत्र के सभी मूल्यों का प्रतिनिधित्व कर सकते हैं; अन्यथा, यह करने के लिए परिवर्तित किया जा सकता unsigned intहै, तो unsigned intथोड़ा-क्षेत्र के सभी मूल्यों का प्रतिनिधित्व कर सकते हैं। यदि बिट-फ़ील्ड अभी तक बड़ा है, तो कोई भी अभिन्न पदोन्नति इस पर लागू नहीं होती है। यदि बिट-फ़ील्ड में एक एन्यूमरेटेड प्रकार है, तो इसे प्रचार उद्देश्यों के लिए उस प्रकार के किसी भी अन्य मान के रूप में माना जाता है।

आपके बाएं ऑपरेंड (बिट-फ़ील्ड) का प्रचार एक उत्पादन करता है int, और इसलिए यह पूरी पारी की अभिव्यक्ति का प्रकार है। इस प्रकार bएक है intप्लेसहोल्डर प्रकार कटौती से भी।