uint8_t कोउट के साथ मुद्रित नहीं किया जा सकता है


146

मुझे C ++ में पूर्णांक के साथ काम करने के बारे में एक अजीब समस्या है।

मैंने एक साधारण प्रोग्राम लिखा, जो एक वैरिएबल के लिए एक मान सेट करता है और फिर उसे प्रिंट करता है, लेकिन यह अपेक्षित रूप से काम नहीं कर रहा है।

मेरे कार्यक्रम में केवल दो पंक्तियाँ हैं:

uint8_t aa = 5;

cout << "value is " << aa << endl;

इस कार्यक्रम का आउटपुट है value is

यानी, यह रिक्त के लिए प्रिंट करता है aa

जब मैं बदलने uint8_tके लिए uint16_tऊपर दिए गए कोड एक आकर्षण की तरह काम करता है।

मैं Ubuntu 12.04 (सटीक पैंगोलिन) का उपयोग करता हूं, 64-बिट, और मेरा संकलक संस्करण है:

gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

2

जवाबों:


151

यह वास्तव में एक रिक्त नहीं छापता है, लेकिन सबसे अधिक मान 5 के साथ एएससीआईआई चरित्र है, जो गैर-मुद्रण योग्य (या अदृश्य) है। कई अदृश्य ASCII वर्ण कोड हैं , उनमें से अधिकांश मूल्य 32 से नीचे हैं, जो वास्तव में रिक्त है।

आपको संख्यात्मक मान को आउटपुट aaकरने के लिए कनवर्ट करना unsigned intहोगा, क्योंकि ostream& operator<<(ostream&, unsigned char)दृश्यमान वर्ण मान को आउटपुट करने की कोशिश करता है।

uint8_t aa=5;

cout << "value is " << unsigned(aa) << endl;

24
चूँकि C स्टाइल की कास्ट्स फेक होती हैं, तो क्या static_cast करना बेहतर नहीं होगा?
टिम सेगिन

37
इसे परिवर्तित किया जाना चाहिए int। एक कास्ट ऐसा करने का एक तरीका है, लेकिन एकमात्र तरीका नहीं है। +aaभी काम करता है।
पीट बेकर

5
int (var) और (int) var वास्तव में एक ही बात नहीं है?
पल्म १m

9
प्रकार (var) का उपयोग करके लिंक किए गए प्रश्न को देखें (var) इसका प्रकार (var) है, जो C कास्ट के समान है - इसे const आदि के साथ आज़माएं, यह इसे हटा देता है!
पल्म १m

13
प्रतिक्रिया "संख्या सी-शैली की जाति कई कारणों से सी ++ के लिए हतोत्साहित करती है।" "int (var) और (int) var वास्तव में एक ही बात नहीं है?" यकीन है कि यह लगता है जैसे आप महसूस नहीं किया था int(var)और (int)varवास्तव में एक ही अर्थ है। वास्तव में उन्हीं कारणों int(var)से हतोत्साहित किया (int)varजाता है, जहां बिल्कुल वही कारण हैं, क्योंकि इसका मतलब बिल्कुल वही है। (मैं समझ सकता हूं कि आप इसके लिए वैसे भी यहां क्यों जाएंगे, हालांकि, इसलिए मैं आपको उपयोग करने की आवश्यकता नहीं कह रहा हूं static_cast। मुझे लगता है कि यहां टिप्पणी का निशान थोड़ा अनावश्यक रूप से भ्रमित हो गया है।)

46

uint8_tसबसे अधिक संभावना एक के typedefलिए किया जाएगा unsigned charostreamवर्ग के लिए एक विशेष अधिभार है unsigned char, यानी यह संख्या 5 है, जो प्रिंट न हो सकने है, इसलिए खाली जगह के साथ चरित्र प्रिंट करता है।


14
मेरी इच्छा है कि मानक वास्तव में इलाज किए गए std :: uint8_t को एक अलग प्रकार के रूप में और न केवल एक फ्रिगिन के टाइपफेड के रूप में। स्ट्रीम ऑब्जेक्ट के साथ संयोजन में उपयोग किए जाने पर इन प्रकारों के लिए चरित्र-शब्दार्थ लागू करने का कोई कारण नहीं है।
विरोध किया

37

किसी भी आदिम डेटा प्रकार के चर से पहले एक unary + ऑपरेटर जोड़ना ASCII वर्ण (चार प्रकार के मामले में) के बजाय मुद्रण योग्य संख्यात्मक मान देगा।

uint8_t aa = 5;
cout<<"value is "<< +aa <<endl;

यह अच्छा है, लेकिन क्यों ++ इलाज सी नहीं है uint8_tके रूप में unsigned charजो संख्यात्मक मानों हो सकता है?
R1S8K

@ R1S8K इस वजह है, जबकि uint8_tबस के डीईएफ़ एक प्रकार है unsigned char, unsigned charअपने आप में नियंत्रित किया जाता है ostream, जैसे charऔर अपने ASCII मूल्य प्रिंट करता है।
हर्ष

@ हर्ष थैंक्स यार! इसलिए यह एक प्रकार का दोष है unsigned charजो बहुत कुछ समझाता है। तो केवल पूर्णांक है int, है ना?
R1S8K

@ R1S8K खैर, सबसे छोटा पूर्णांक प्रकार होगा short intजो 2 बाइट्स लेता है। पूर्णांक प्रकार के कुछ अन्य रूपांतर भी हैं।
हर्ष

@ यह भी मुझे लगता है कि जब प्रोग्रामिंग और वेरिएबल्स की घोषणा की जाती है, तो इससे कोई फर्क नहीं पड़ता कि मैं एक ऐसे वैरिएबल की घोषणा करता हूं जो केवल छोटी संख्या के साथ ही व्यवहार करेगा, जैसे 250 बड़े रजिस्टर आकार के साथ longया उससे अधिक नहीं intक्योंकि कंपाइलर रैम या फ्लैश के उपयोग को अनुकूलित करेगा। उस रजिस्टर को भरने के हिसाब से क्या मैं सही हूं?
R1S8K

16

ऐसा इसलिए है क्योंकि आउटपुट ऑपरेटर uint8_tएक की तरह व्यवहार करता है char( uint8_tयह आमतौर पर सिर्फ एक उपनाम है unsigned char), इसलिए यह ASCII कोड (जो कि सबसे आम चरित्र एन्कोडिंग सिस्टम है) के साथ चरित्र को प्रिंट करता है 5

उदाहरण देखें यह संदर्भ


क्यों? सी संकलक इसे एक संख्या के रूप में मानता है। मुझे लगता है कि C ++ इस बिंदु पर अलग है।
R1S8K

@PerchEagle यदि आप लिंक किए गए संदर्भ को पढ़ते हैं, तो आप देखेंगे कि ऑपरेटर दोनों signedऔर unsignedपात्रों के लिए अतिभारित है (सादे से परे charजो सी ++ में वास्तव में एक तीसरा अलग प्रकार है)। तो अगर (बहुत संभावना है) के uint8_tलिए एक उपनाम unsigned charहै जिसका उपयोग किया जाएगा।
कुछ प्रोग्रामर

क्या आप इस धागे पर मेरे उत्तर की जाँच कर सकते हैं और मुझे बता सकते हैं कि मेरा उत्तर सही है या नहीं? stackoverflow.com/questions/15585267/… , मेरा जवाब आखिरी वाले से पहले है। बहुत बहुत धन्यवाद।
R1S8K

14
  • का इस्तेमाल कर रही ADL (तर्क पर निर्भर नाम देखने):

    #include <cstdint>
    #include <iostream>
    #include <typeinfo>
    
    namespace numerical_chars {
    inline std::ostream &operator<<(std::ostream &os, char c) {
        return std::is_signed<char>::value ? os << static_cast<int>(c)
                                           : os << static_cast<unsigned int>(c);
    }
    
    inline std::ostream &operator<<(std::ostream &os, signed char c) {
        return os << static_cast<int>(c);
    }
    
    inline std::ostream &operator<<(std::ostream &os, unsigned char c) {
        return os << static_cast<unsigned int>(c);
    }
    }
    
    int main() {
        using namespace std;
    
        uint8_t i = 42;
    
        {
            cout << i << endl;
        }
    
        {
            using namespace numerical_chars;
            cout << i << endl;
        }
    }

    उत्पादन:

    *
    42
  • एक कस्टम स्ट्रीम मैनिपुलेटर भी संभव होगा।

  • यूनीरी प्लस ऑपरेटर एक साफ मुहावरा भी है ( cout << +i << endl)।

8
नहीं है चुंबन अभी भी एक मान्य प्रतिमान ??
πάν 0α


4
@ ofν cαῥεῖ ठीक है, c ++ कोड में c स्टाइल कास्ट के टन बना रहे हैं, फिर भी, कोई भी व्यक्ति इस तरह से उत्पादक होने के लिए स्वतंत्र है, जिस माहौल में वह सबसे अधिक फिट बैठता है।
काली मिर्च_चिको

5
@ @νπάαῥεῖ गंभीरता से? कार्यात्मक शैली कास्ट, भी, सिर्फ c शैली कास्टिंग है। C के दायरे को छोड़ने में किसी एक को बदलने से कुछ भी मदद नहीं करता है, चेक करें: stackoverflow.com/a/4775807/1000g2 । pete-becker ने आपके उत्तर पर भी यह टिप्पणी की, लेकिन आपको लगता है कि वह अपनी अंतिम टिप्पणी से चूक गए हैं।
मिर्च_चिको

3
यह समाधान बहुत ही सुरुचिपूर्ण और प्रभावी है, क्योंकि यह टेम्पलेट्स के साथ काम करता है। वास्तव में, यह एकमात्र समाधान है जो मैंने देखा है जो मेरे लिए काम करता है। एक चेतावनी हालांकि, पहले फ़ंक्शन में एक बग है, क्योंकि 'ओएस' एक एकल प्रकार से जुड़ा हुआ है, और इसलिए, या तो हस्ताक्षरित या अहस्ताक्षरित मूल्य ऑपरेटर के गलत संस्करण में भेजा जाएगा << ()। यह फिक्स काफी सरल है:return std::is_signed<char>::value ? os << static_cast<int>(c) : os << static_cast<unsigned int>(c);
जॉर्ज


4

के operator<<()बीच अधिभार istreamऔर charएक गैर-सदस्यीय फ़ंक्शन है। ए char(या क uint8_t) के रूप में इलाज करने के लिए आप स्पष्ट रूप से सदस्य फ़ंक्शन का उपयोग कर सकते हैं int

#include <iostream>
#include <cstddef>

int main()
{
   uint8_t aa=5;

   std::cout << "value is ";
   std::cout.operator<<(aa);
   std::cout << std::endl;

   return 0;
}

आउटपुट:

value is 5

2

जैसा कि अन्य लोगों ने कहा है कि समस्या उत्पन्न होने से पहले क्योंकि मानक धारा हस्ताक्षरित चार और अहस्ताक्षरित चार को एकल वर्ण मानती है और संख्या के रूप में नहीं।

यहां न्यूनतम कोड परिवर्तन के साथ मेरा समाधान है:

uint8_t aa = 5;

cout << "value is " << aa + 0 << endl;

"+0"फ़्लोटिंग पॉइंट सहित किसी भी संख्या के साथ जोड़ना सुरक्षित है।

पूर्णांक प्रकारों के लिए यह परिणाम के प्रकार को बदल जाएगा intयदि sizeof(aa) < sizeof(int)। और यह प्रकार नहीं बदलेगा यदि sizeof(aa) >= sizeof(int)

यह समाधान int8_tस्ट्रीम करने के लिए मुद्रित करने की तैयारी के लिए भी अच्छा है जबकि कुछ अन्य समाधान इतने अच्छे नहीं हैं:

int8_t aa = -120;

cout << "value is " << aa + 0 << endl;
cout << "bad value is " << unsigned(aa) << endl;

आउटपुट:

value is -120
bad value is 4294967176

काली मिर्च_chico और τνῥεῖα Solution द्वारा दिए गए ADL के साथ PS समाधान वास्तव में सुंदर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.