C में हेक्साडेसिमल अक्षरों की छपाई


103

मैं वर्णों की एक पंक्ति में पढ़ने की कोशिश कर रहा हूं, फिर वर्णों के समरूप हेक्साडेसिमल का प्रिंट आउट लें।

उदाहरण के लिए, यदि मेरे पास एक स्ट्रिंग है "0xc0 0xc0 abc123", जहां पहले 2 वर्ण c0हेक्स में हैं और शेष वर्ण abc123ASCII में हैं, तो मुझे मिलना चाहिए

c0 c0 61 62 63 31 32 33

हालाँकि, printfउपयोग %xमुझे देता है

ffffffc0 ffffffc0 61 62 63 31 32 33

मैं कैसे उत्पादन प्राप्त कर सकता हूँ जिसे मैं बिना चाहता हूँ "ffffff"? और ऐसा क्यों है कि केवल c0 (और 80) में ही है ffffff, लेकिन अन्य वर्ण नहीं हैं?


स्ट्रिंग जो आपके बाइट्स की सरणी से मेल खाती है ..."\xc0\xc0abc123"
burito

जवाबों:


132

आप देख रहे हैं ffffffक्योंकि charआपके सिस्टम पर हस्ताक्षर किए गए हैं। सी में, इस तरह के रूप में vararg कार्यों printfसभी पूर्णांकों की तुलना में छोटे को बढ़ावा देंगे intकरने के लिए int। चूंकि charएक पूर्णांक (आपके मामले में 8-बिट हस्ताक्षरित पूर्णांक) है, इसलिए आपके चार्ट intको साइन-एक्सटेंशन के माध्यम से प्रचारित किया जा रहा है ।

के बाद से c0और 80एक अग्रणी 1-बिट है (और एक 8 बिट पूर्णांक के रूप में नकारात्मक हैं), वे साइन-बढ़ाया जा रहा है, जबकि अपनी नमूने में दूसरों को नहीं कर रहे हैं।

char    int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061

यहाँ एक समाधान है:

char ch = 0xC0;
printf("%x", ch & 0xff);

यह ऊपरी बिट्स को बाहर निकाल देगा और केवल निचले 8 बिट्स को रखेगा जो आप चाहते हैं।


15
एक डाली का उपयोग कर मेरा समाधान unsigned charx86-64 के लिए gcc4.6 में एक निर्देश छोटा है ...
lvella

1
शायद मैं मदद कर सकता हूँ। यह (तकनीकी रूप से) अपरिभाषित व्यवहार है क्योंकि विनिर्देशक xको एक अहस्ताक्षरित प्रकार की आवश्यकता होती है, लेकिन ch को int में बढ़ावा दिया जाता है। सही कोड को केवल अहस्ताक्षरित करने के लिए ch डाली जाएगी, या अहस्ताक्षरित char और विनिर्देशक के लिए एक कास्ट का उपयोग करें hhx:।
2501

1
अगर मेरे पास है printf("%x", 0), तो कुछ भी नहीं छपा है।
गुस्तावो मीरा

यह कुछ भी प्रिंट नहीं करता है क्योंकि न्यूनतम 0 पर सेट है। इसे ठीक करने के लिए, printf("%.2x", 0);जो न्यूनतम 2 को आकर्षित करने वाले वर्णों को बढ़ावा देगा। अधिकतम सेट करने के लिए। एक नंबर के साथ। उदाहरण के लिए, आप केवल २ अक्षरों को खींच कर बाध्य कर सकते हैंprintf("%2.2x", 0);
user2262111

किसी भी कारण से क्यों @ brutal_lobster के उत्तर में printf("%x", ch & 0xff)उपयोग करने से बेहतर होना चाहिए ? printf("%02hhX", a)
मैक्सचेलपिजिग

62

दरअसल, इंट में टाइप रूपांतरण है। इसके अलावा, आप% hhx विनिर्देशक का उपयोग करके चार्ट को टाइप करने के लिए बाध्य कर सकते हैं।

printf("%hhX", a);

अधिकांश मामलों में आप शून्य के साथ दूसरा वर्ण भरने के लिए न्यूनतम लंबाई निर्धारित करना चाहेंगे:

printf("%02hhX", a);

आईएसओ / आईईसी 9899: 201x कहता है:

7 लंबाई संशोधक और उनके अर्थ हैं: hh निर्दिष्ट करता है कि निम्नलिखित d, i, o, u, x, या X रूपांतरण विनिर्देशक एक हस्ताक्षरित चार या अहस्ताक्षरित चार तर्क पर लागू होता है (पूर्णांक पदोन्नति के अनुसार तर्क को बढ़ावा दिया गया होगा) लेकिन इसका मूल्य छपाई से पहले हस्ताक्षरित चार या अहस्ताक्षरित चार में परिवर्तित हो जाएगा); या कि एक निम्नलिखित


30

आप एक अहस्ताक्षरित चार बना सकते हैं:

unsigned char c = 0xc5;

इसे छापना C5और नहीं देना होगा ffffffc5

केवल 127 से अधिक बड़े वर्णों को मुद्रित किया जाता है ffffffक्योंकि वे नकारात्मक हैं (चार्ट पर हस्ताक्षर किए गए हैं)।

या आप charमुद्रण करते समय कास्ट कर सकते हैं :

char c = 0xc5; 
printf("%x", (unsigned char)c);

3
+1 वास्तविक सर्वश्रेष्ठ उत्तर, डेटा घोषणा के जितना संभव हो उतना स्पष्ट टाइपिंग (लेकिन करीब नहीं)।
बॉब स्टीन

13

आप शायद एक charचर में मान 0xc0 का भंडारण कर रहे हैं , जो शायद एक हस्ताक्षरित प्रकार है, और आपका मूल्य नकारात्मक है (सबसे महत्वपूर्ण बिट सेट)। फिर, जब मुद्रण होता है, तो इसे परिवर्तित किया जाता है int, और शब्दार्थ समतुल्य बनाए रखने के लिए, कंपाइलर 0xff के साथ अतिरिक्त बाइट्स को पैड करता है, इसलिए नकारात्मक intआपके नकारात्मक का समान संख्यात्मक मान होगा char। इसे ठीक करने के लिए, बस unsigned charछपाई करते समय:

printf("%x", (unsigned char)variable);

13

आप यह hhबताने के लिए उपयोग कर सकते हैं printfकि तर्क एक अहस्ताक्षरित चार है। उपयोग 0शून्य गद्दी पाने के लिए और 22 के लिए चौड़ाई सेट करने xया Xकम / अपरकेस हेक्स पात्रों के लिए।

uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"

संपादित करें : यदि पाठकों को 2501 के बारे में चिंतित हैं कि यह किसी भी तरह से 'सही' प्रारूप निर्दिष्ट नहीं है, तो मैं सुझाव देता हूं कि वे फिर से printfलिंक पढ़ें । विशेष रूप से:

भले ही% c को आर्गुमेंट की उम्मीद है, लेकिन जब एक वैरिएडिक फंक्शन को बुलाया जाता है, तब होने वाले पूर्णांक प्रमोशन की वजह से चार पास करना सुरक्षित होता है।

फिक्स्ड-चौड़ाई वर्ण प्रकार (int8_t, आदि) के लिए सही रूपांतरण विनिर्देश हेडर <cinttypes>(C ++) या <inttypes.h>(C) में परिभाषित किए गए हैं (हालांकि PRIdMAX, PRIuMAX, आदि% jd,% ju, आदि का पर्याय है)

के रूप में हस्ताक्षरित बनाम अहस्ताक्षरित के बारे में उसकी बात, इस मामले में कोई फर्क नहीं पड़ता क्योंकि मूल्यों को हमेशा सकारात्मक होना चाहिए और एक हस्ताक्षरित इंट में आसानी से फिट होना चाहिए। वैसे भी कोई हस्ताक्षरित हेक्साइडएक्सिमल प्रारूप निर्दिष्ट नहीं है।

संपादित करें २ : ("कब-कब-कब-आप-गलत हैं" संस्करण):

यदि आप पृष्ठ 311 (पीडीएफ का 329) पर वास्तविक C11 मानक पढ़ते हैं:

hh: निर्दिष्ट है कि एक के बाद d, i, o, u, x, या Xरूपांतरण विनिर्देशक पर लागू होता है signed charया unsigned charतर्क (तर्क पूर्णांक प्रोन्नति के अनुसार पदोन्नत जाएगा है, लेकिन अपने मूल्य के लिए परिवर्तित किया जाएगा signed charया unsigned charमुद्रण से पहले); या कि निम्न nरूपांतरण विनिर्देशक एक सूचक के लिए एक signed charतर्क पर लागू होता है ।


विनिर्देशक uint8_t प्रकार के लिए सही नहीं हैं। निश्चित चौड़ाई के प्रकार विशेष प्रिंट विनिर्देशक का उपयोग करते हैं। देखें:inttypes.h
2501

हाँ, लेकिन सभी varargs पूर्णांक int को संक्षेप में पदोन्नत किया जाता है।
टिम्मम्म

यह हो सकता है, लेकिन जहां तक ​​सी को परिभाषित किया गया है, अगर आप सही स्पेसिफायर का उपयोग नहीं करते हैं तो व्यवहार अपरिभाषित है।
2501

लेकिन% x है सही विनिर्देशक। ( charऔर unsigned charइसे बढ़ावा दिया जाता है int) [ en.cppreference.com/w/cpp/language/variadic_arguments] । आपको केवल उन चीजों के लिए PRI स्पेसिफिकर्स का उपयोग करने की आवश्यकता होगी जो आपके प्लेटफ़ॉर्म में फिट नहीं हैं int- जैसे unsigned int
टिमम्म

%xअहस्ताक्षरित int नहीं int के लिए सही है। प्रकार चार और अहस्ताक्षरित चार को इंट में पदोन्नत किया जाता है। इसके अलावा इसमें कोई गारंटी नहीं है कि uint8_t को अहस्ताक्षरित चार के रूप में परिभाषित किया गया है।
2501

2

आप शायद एक हस्ताक्षरित चार सरणी से छपाई कर रहे हैं। या तो एक अहस्ताक्षरित चार सरणी से प्रिंट करें या 0xff के साथ मान को मास्क करें: जैसे कि ar [i] & 0xFF। C0 मान को बढ़ाया जा रहा है क्योंकि उच्च (साइन) बिट सेट है।


-1

कुछ इस तरह की कोशिश करो:

int main()
{
    printf("%x %x %x %x %x %x %x %x\n",
        0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}

जो इस का उत्पादन करता है:

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