uint8_t बनाम अहस्ताक्षरित चार


231

C में uint8_tओवर का उपयोग करने का क्या फायदा unsigned charहै?

मुझे पता है कि लगभग हर प्रणाली के uint8_tलिए सिर्फ एक टाइपराइफ है unsigned char, इसलिए इसका उपयोग क्यों करें?

जवाबों:


225

यह आपके इरादे को दस्तावेज करता है - आप एक चरित्र के बजाय छोटी संख्याओं का भंडारण करेंगे।

यह भी अच्छा लग रहा है अगर आप अन्य टाइपडेफ़्स जैसे uint16_tया का उपयोग कर रहे हैं int32_t


1
मूल प्रश्न में यह स्पष्ट नहीं था कि हम एक मानक प्रकार के बारे में बात कर रहे हैं या नहीं। मुझे यकीन है कि वर्षों से इस नामकरण सम्मेलन के कई रूप हैं।
मार्क रैनसम

8
स्पष्ट रूप से इरादे का उपयोग करना unsigned charया signed charदस्तावेजों का उपयोग करना , क्योंकि अनियंत्रित charवह है जो दिखाता है कि आप पात्रों के साथ काम कर रहे हैं।
कैफे

9
मैंने सोचा unsignedथा unsigned intकि परिभाषा से एक अनकहा था ?
मार्क रैनसम

5
@endolith, स्ट्रिंग के लिए uint8_t का उपयोग करना गलत नहीं है, लेकिन यह निश्चित रूप से अजीब है।
मार्क रैनसम

5
@endolith, मुझे लगता है कि मैं UTF8 पाठ के साथ uint8_t के लिए एक मामला बना सकता हूं। वास्तव में, charयह एक चरित्र का अर्थ लगता है, जबकि UTF8 स्ट्रिंग के संदर्भ में, यह एक मल्टीबैट चरित्र का सिर्फ एक बाइट हो सकता है। Uint8_t का उपयोग करने से यह स्पष्ट हो सकता है कि किसी व्यक्ति को हर स्थिति में एक चरित्र की उम्मीद नहीं करनी चाहिए - दूसरे शब्दों में कि स्ट्रिंग / सरणी के प्रत्येक तत्व एक मनमाना पूर्णांक है जिसके बारे में किसी को कोई अर्थपूर्ण अनुमान नहीं लगाना चाहिए। बेशक सभी सी प्रोग्रामर यह जानते हैं, लेकिन यह शुरुआती लोगों को सही सवाल पूछने के लिए प्रेरित कर सकता है।
tne

70

बस पांडित्यपूर्ण होने के लिए, कुछ प्रणालियों में 8 बिट प्रकार नहीं हो सकता है। विकिपीडिया के अनुसार :

एन = 8, 16, 32, या 64 के लिए सटीक-चौड़ाई पूर्णांक प्रकारों को परिभाषित करने के लिए एक कार्यान्वयन की आवश्यकता होती है और यदि केवल यह किसी भी प्रकार की आवश्यकताओं को पूरा करता है। उन्हें किसी अन्य एन के लिए परिभाषित करने की आवश्यकता नहीं है, भले ही वह उपयुक्त प्रकारों का समर्थन करता हो।

तो uint8_tअस्तित्व की गारंटी नहीं है, हालांकि यह उन सभी प्लेटफार्मों के लिए होगा जहां 8 बिट्स = 1 बाइट। कुछ एम्बेडेड प्लेटफॉर्म अलग हो सकते हैं, लेकिन यह बहुत दुर्लभ है। कुछ प्रणालियाँ charप्रकारों को 16 बिट्स के रूप में परिभाषित कर सकती हैं , ऐसी स्थिति में संभवतः किसी भी प्रकार का 8-बिट प्रकार नहीं होगा।

उस (मामूली) मुद्दे के अलावा, @ मर्क रैंसम का जवाब मेरी राय में सबसे अच्छा है। एक का उपयोग करें जो सबसे स्पष्ट रूप से दिखाता है कि आप किस डेटा के लिए उपयोग कर रहे हैं।

इसके अलावा, मैं आपको मान रहा हूं uint8_t( stdint.hहेडर में प्रदान किए गए C99 से मानक टाइपडिफ़ ) के बजाय uint_8(किसी भी मानक का हिस्सा नहीं)।


3
@ कफ, सरासर जिज्ञासा से बाहर - क्या आप कुछ का वर्णन करने के लिए लिंक कर सकते हैं? मुझे पता है कि वे मौजूद हैं क्योंकि किसी ने comp.lang.c ++ में एक का उल्लेख किया है (और इसके लिए डेवलपर डॉक्स से लिंक किया गया है)। सी / सी ++ प्रकार की गारंटी के बारे में मध्यम चर्चा बहुत कमजोर है, लेकिन मुझे वह धागा अब और नहीं मिल सकता है, और यह हमेशा काम आता है। संदर्भ के लिए किसी भी इसी तरह की चर्चा में :)
पावेल मिनावे

3
"कुछ सिस्टम चार प्रकारों को 16 बिट्स के रूप में परिभाषित कर सकते हैं, जिस स्थिति में संभवतः किसी भी प्रकार का 8-बिट प्रकार नहीं होगा।" - और मेरे द्वारा कुछ गलत आपत्तियों के बावजूद, पावेल ने अपने जवाब में प्रदर्शित किया है कि अगर चार बिट्स हैं, तो भी यदि कंपाइलर 8 बिट प्रकार प्रदान करता है, तो उसे इसे कॉल नहीं करना चाहिएuint8_t (या इसे टाइप करें )। ऐसा इसलिए है क्योंकि 8 बिट प्रकार के भंडारण प्रतिनिधित्व में अप्रयुक्त बिट्स होंगे, जिनके uint8_tपास नहीं होना चाहिए।
स्टीव जेसप

3
SHARC आर्किटेक्चर में 32-बिट शब्द हैं। देखें en.wikipedia.org/wiki/... जानकारी के लिए।
बीकानेर

2
और TI के C5000 DSP (जो OMAP1 और OMAP2 में थे) 16bit हैं। मुझे लगता है कि OMAP3 के लिए वे C6000- सीरीज़ में गए, जिसमें 8bit का चार्ट था।
स्टीव जेसप

4
N3242 में खुदाई - "वर्किंग ड्राफ्ट, प्रोग्रामिंग लैंग्वेज के लिए मानक C ++", सेक्शन 18.4.1 <cstdint> सिनोप्सिस कहता है - typedef unsigned integer type uint8_t; // optional तो, संक्षेप में, uint__ को परिभाषित करने के लिए एक C ++ मानक अनुरूप लाइब्रेरी की आवश्यकता नहीं है (टिप्पणी देखें / वैकल्पिक) )
नाइटलाइटर

43

संपूर्ण बिंदु कार्यान्वयन-स्वतंत्र कोड लिखना है। unsigned char8-बिट प्रकार होने की गारंटी नहीं है। uint8_tहै (यदि उपलब्ध हो)।


4
... अगर यह एक प्रणाली पर मौजूद है, लेकिन यह बहुत दुर्लभ होने जा रहा है। +1
क्रिस लुत्ज़

2
अच्छी तरह से अगर आप वास्तव में अपने कोड के साथ एक सिस्टम पर संकलित नहीं करने के कारण परेशान थे क्योंकि uint8_t मौजूद नहीं था, तो आप स्वचालित रूप से uint8_t की सभी घटनाओं को बदलकर अहस्ताक्षरित चार या आपके लिए अधिक उपयोगी कुछ को बदलने के लिए उपयोग कर सकते हैं।
बाज़

2
@bazz - यदि आप यह मान रहे हैं कि यह एक 8-बिट प्रकार है जिसे आप नहीं कर सकते हैं - उदाहरण के लिए रिमोट सिस्टम द्वारा बाइटवाइज़ फैशन में पैक किए गए डेटा को अनपैक करना। निहित धारणा यह है कि uint8_t के मौजूद न होने का कारण एक प्रोसेसर पर है जहां एक चार्ट 8 बिट्स से अधिक है।
क्रिस स्ट्रैटन

जोर में जोर देना
bazz

3
@ गलत गलत दावे से मुझे डर लगता है। 1 बाइट के लिए sizeof(unsigned char)लौटेगा 1। लेकिन अगर एक सिस्टम चार और int का आकार समान है, उदाहरण के लिए, 16-बिट्स तो sizeof(int)भी वापस आ जाएगी1
Toby

7

जैसा कि आपने कहा, " लगभग हर प्रणाली"।

charशायद बदलने की कम संभावना में से एक है, लेकिन एक बार जब आप uint16_tदोस्तों का उपयोग करना शुरू करते हैं , तो uint8_tबेहतर मिश्रणों का उपयोग करते हैं , और यहां तक ​​कि कोडन मानक का हिस्सा भी हो सकते हैं।


7

मेरे अनुभव में दो जगह हैं जहां हम 8 बिट्स (और uint16_t, आदि) का मतलब करने के लिए uint8_t का उपयोग करना चाहते हैं और जहां हमारे पास 8 बिट्स से छोटे क्षेत्र हो सकते हैं। दोनों स्थान वे स्थान हैं जहां अंतरिक्ष मायने रखता है और हमें अक्सर डिबगिंग करते समय डेटा के एक कच्चे डंप को देखने की आवश्यकता होती है और यह दर्शाता है कि क्या प्रतिनिधित्व करता है यह जल्दी से निर्धारित करने में सक्षम होना चाहिए।

पहला आरएफ प्रोटोकॉल में है, विशेष रूप से संकीर्ण-बैंड सिस्टम में। इस वातावरण में हमें एक ही संदेश में जितनी जानकारी हो सकती है उतनी पैक करने की आवश्यकता है। दूसरा फ्लैश स्टोरेज में है जहां हमारे पास बहुत सीमित स्थान हो सकता है (जैसे कि एम्बेडेड सिस्टम)। दोनों मामलों में हम एक पैक डेटा संरचना का उपयोग कर सकते हैं जिसमें कंपाइलर हमारे लिए पैकिंग और अनपैकिंग का ध्यान रखेगा:

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

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

पैक्ड संरचनाओं का उपयोग करने के साथ कुछ कैविएट हैं। सबसे बड़ी गोटा यह है कि आपको किसी सदस्य के पते को डीफ्रेंस्ड करने से बचना चाहिए। म्यूटिबेट संरेखित शब्दों वाले सिस्टम पर, यह एक गलत अपवाद हो सकता है - और एक coredump।

कुछ लोग प्रदर्शन के बारे में भी चिंता करेंगे और तर्क देंगे कि इन पैक्ड संरचनाओं का उपयोग करने से आपकी प्रणाली धीमी हो जाएगी। यह सच है कि, पर्दे के पीछे, कंपाइलर बिना डेटा वाले सदस्यों को एक्सेस करने के लिए कोड जोड़ता है। आप अपने IDE में असेंबली कोड को देखकर देख सकते हैं।

लेकिन चूंकि संचार और डेटा स्टोरेज के लिए पैक्ड स्ट्रक्चर्स सबसे उपयोगी होते हैं तो मेमोरी में काम करने के दौरान डेटा को नॉन-पैक्ड प्रतिनिधित्व में निकाला जा सकता है। आम तौर पर हमें वैसे भी मेमोरी में पूरे डेटा पैकेट के साथ काम करने की आवश्यकता नहीं होती है।

यहाँ कुछ प्रासंगिक चर्चा है:

प्रागम पैक (1) और न ही __attribute__ (((1))) काम करता है

क्या gcc का __attribute __ ((पैक)) / #pragma पैक असुरक्षित है?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html


6

थोड़ा है। पोर्टेबिलिटी के दृष्टिकोण से, char8 बिट्स से छोटा नहीं हो सकता है, और कुछ भी छोटा नहीं हो सकता है char, इसलिए यदि किसी दिए गए सी कार्यान्वयन में एक अहस्ताक्षरित 8-बिट पूर्णांक प्रकार है, तो यह होने जा रहा है char। वैकल्पिक रूप से, इसमें एक भी नहीं हो सकता है, जिस बिंदु पर कोई भी typedefचाल चलनी है।

इसका उपयोग आपके कोड को इस अर्थ में बेहतर ढंग से करने के लिए किया जा सकता है कि यह स्पष्ट हो कि आपको वहां 8-बिट बाइट्स की आवश्यकता है और कुछ नहीं। लेकिन व्यवहार में यह एक वाजिब उम्मीद है कि वस्तुतः पहले से ही कहीं भी (डीएसपी प्लेटफ़ॉर्म हैं, जिस पर यह सच नहीं है, लेकिन आपके कोड के चलने की संभावना पतली है, और आप बस अपने प्रोग्राम के शीर्ष पर स्थैतिक मुखर का उपयोग करके त्रुटि कर सकते हैं। ऐसा मंच)।


7
@Skizz - नहीं, मानक को unsigned char0 और 255 के बीच मान रखने में सक्षम होना चाहिए । यदि आप ऐसा कर सकते हैं तो 4 बिट्स में, मेरी टोपी आपके पास है।
क्रिस लुत्ज

1
"यह थोड़ा अधिक बोझिल होगा" - इस मायने में बोझिल कि आपको चलना होगा (तैरना, एक विमान पकड़ना, आदि) कम्पाइलर लेखक के सभी तरीके, जहां सिर के पीछे उन्हें थप्पड़ मारते हैं , और उन्हें uint8_tकार्यान्वयन में जोड़ें । मुझे आश्चर्य है, 16bit चार्ट के साथ डीएसपी के लिए कंपाइलर आमतौर पर लागू होते हैं uint8_t, या नहीं?
स्टीव जेसप

6
वैसे, एक दूसरे विचार पर, "मुझे वास्तव में 8 बिट्स की आवश्यकता है" कहने के लिए यह सबसे सरल तरीका है - #include <stdint.h>और उपयोग करें uint8_t। यदि प्लेटफ़ॉर्म के पास है, तो यह आपको दे देगा। यदि प्लेटफ़ॉर्म नहीं है, तो आपका प्रोग्राम संकलित नहीं होगा, और इसका कारण स्पष्ट और सीधा होगा।
पावेल मिनाएव

2
फिर भी कोई सिगार नहीं, क्षमा करें: "अहस्ताक्षरित चार के अलावा अन्य पूर्णांक प्रकारों के लिए, वस्तु प्रतिनिधित्व के बिट्स को दो समूहों में विभाजित किया जाएगा: मूल्य बिट्स और पैडिंग बिट्स ... यदि एन मूल्य बिट्स हैं, तो प्रत्येक बिट एक अलग प्रतिनिधित्व करेगा 1 और 2 ^ (N-1) के बीच 2 की शक्ति, ताकि उस प्रकार की वस्तुएं 0 से 2 ^ (N-1) तक शुद्ध द्विआधारी प्रतिनिधित्व का उपयोग कर मूल्यों का प्रतिनिधित्व करने में सक्षम हों ... टाइप किए गए नाम intN_t एक नामित करता है चौड़ाई एन के साथ हस्ताक्षरित पूर्णांक प्रकार, कोई पैडिंग बिट्स और एक दो का पूरक प्रतिनिधित्व नहीं। "
पावेल मिनाएव

1
यदि आपको सिर्फ अंकगणित मोडुलो की आवश्यकता है, तो अहस्ताक्षरित बिटफील्ड ठीक (यदि असुविधाजनक) हो तो। जब आपको ज़रूरत हो, तो कहें, ओट्स की एक सरणी, जिसमें कोई पैडिंग नहीं है, जब आप एसओएल करते हैं। नैतिक कहानी डीएसपी के लिए कोड करने के लिए नहीं है, और उचित, ईमानदार-टू-गॉड 8-बिट चार आर्किटेक्चर के लिए छड़ी :)
पावेल मिनावे

4

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


जब मैंने यह पूछा तो मैं निश्चित रूप से धारावाहिक पर सांप्रदायिकता के लिए एक सरल प्रोटोकॉल था।
लिंडन व्हाइट

2

लगभग हर प्रणाली पर मैं uint8_t == अहस्ताक्षरित चार से मिला हूं, लेकिन यह सी मानक द्वारा गारंटी नहीं है। यदि आप पोर्टेबल कोड लिखने की कोशिश कर रहे हैं और यह मायने रखता है कि मेमोरी किस आकार की है, तो uint8_t का उपयोग करें। अन्यथा अहस्ताक्षरित चार का उपयोग करें।


3
uint8_t 8-बिट unsigned charहोने पर हमेशा श्रेणी और पैडिंग का आकार (कोई नहीं) होता unsigned charहै। जब unsigned char8-बिट uint8_tनहीं है , तो मौजूद नहीं है।
chux -

@chux, क्या आपके पास मानक के सटीक स्थान का संदर्भ है जहां वह ऐसा कहता है? तो unsigned char8 बिट, है uint8_tएक होने की गारंटी typedefक्या है और नहीं एक typedefएक की विस्तारित अहस्ताक्षरित पूर्णांक प्रकार ?
18:56 बजे hsivonen

@sivonen "मानक में सटीक स्थान जहां वह ऐसा कहता है?" -> नहीं - अभी तक 7.20.1.1 देखें। यह आसानी से घटाया जाता है unsigned char/signed char/charक्योंकि सबसे छोटे प्रकार हैं - 8 बिट से छोटा नहीं। unsigned charकोई पैडिंग नहीं है। होने के uint8_tलिए, यह 8-बिट्स होना चाहिए, कोई पैडिंग नहीं है, एक कार्यान्वयन प्रदान करने के कारण मौजूद है पूर्णांक प्रकार: न्यूनतम आवश्यकताओं का मिलान unsigned char। जैसा कि "... एक टाइपराइफ़ होने की गारंटी है ..." पोस्ट करने के लिए एक अच्छा प्रश्न लगता है।
chux -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.