C में uint8_t
ओवर का उपयोग करने का क्या फायदा unsigned char
है?
मुझे पता है कि लगभग हर प्रणाली के uint8_t
लिए सिर्फ एक टाइपराइफ है unsigned char
, इसलिए इसका उपयोग क्यों करें?
C में uint8_t
ओवर का उपयोग करने का क्या फायदा unsigned char
है?
मुझे पता है कि लगभग हर प्रणाली के uint8_t
लिए सिर्फ एक टाइपराइफ है unsigned char
, इसलिए इसका उपयोग क्यों करें?
जवाबों:
यह आपके इरादे को दस्तावेज करता है - आप एक चरित्र के बजाय छोटी संख्याओं का भंडारण करेंगे।
यह भी अच्छा लग रहा है अगर आप अन्य टाइपडेफ़्स जैसे uint16_t
या का उपयोग कर रहे हैं int32_t
।
unsigned char
या signed char
दस्तावेजों का उपयोग करना , क्योंकि अनियंत्रित char
वह है जो दिखाता है कि आप पात्रों के साथ काम कर रहे हैं।
unsigned
था unsigned int
कि परिभाषा से एक अनकहा था ?
char
यह एक चरित्र का अर्थ लगता है, जबकि UTF8 स्ट्रिंग के संदर्भ में, यह एक मल्टीबैट चरित्र का सिर्फ एक बाइट हो सकता है। Uint8_t का उपयोग करने से यह स्पष्ट हो सकता है कि किसी व्यक्ति को हर स्थिति में एक चरित्र की उम्मीद नहीं करनी चाहिए - दूसरे शब्दों में कि स्ट्रिंग / सरणी के प्रत्येक तत्व एक मनमाना पूर्णांक है जिसके बारे में किसी को कोई अर्थपूर्ण अनुमान नहीं लगाना चाहिए। बेशक सभी सी प्रोग्रामर यह जानते हैं, लेकिन यह शुरुआती लोगों को सही सवाल पूछने के लिए प्रेरित कर सकता है।
बस पांडित्यपूर्ण होने के लिए, कुछ प्रणालियों में 8 बिट प्रकार नहीं हो सकता है। विकिपीडिया के अनुसार :
एन = 8, 16, 32, या 64 के लिए सटीक-चौड़ाई पूर्णांक प्रकारों को परिभाषित करने के लिए एक कार्यान्वयन की आवश्यकता होती है और यदि केवल यह किसी भी प्रकार की आवश्यकताओं को पूरा करता है। उन्हें किसी अन्य एन के लिए परिभाषित करने की आवश्यकता नहीं है, भले ही वह उपयुक्त प्रकारों का समर्थन करता हो।
तो uint8_t
अस्तित्व की गारंटी नहीं है, हालांकि यह उन सभी प्लेटफार्मों के लिए होगा जहां 8 बिट्स = 1 बाइट। कुछ एम्बेडेड प्लेटफॉर्म अलग हो सकते हैं, लेकिन यह बहुत दुर्लभ है। कुछ प्रणालियाँ char
प्रकारों को 16 बिट्स के रूप में परिभाषित कर सकती हैं , ऐसी स्थिति में संभवतः किसी भी प्रकार का 8-बिट प्रकार नहीं होगा।
उस (मामूली) मुद्दे के अलावा, @ मर्क रैंसम का जवाब मेरी राय में सबसे अच्छा है। एक का उपयोग करें जो सबसे स्पष्ट रूप से दिखाता है कि आप किस डेटा के लिए उपयोग कर रहे हैं।
इसके अलावा, मैं आपको मान रहा हूं uint8_t
( stdint.h
हेडर में प्रदान किए गए C99 से मानक टाइपडिफ़ ) के बजाय uint_8
(किसी भी मानक का हिस्सा नहीं)।
uint8_t
(या इसे टाइप करें )। ऐसा इसलिए है क्योंकि 8 बिट प्रकार के भंडारण प्रतिनिधित्व में अप्रयुक्त बिट्स होंगे, जिनके uint8_t
पास नहीं होना चाहिए।
typedef unsigned integer type uint8_t; // optional
तो, संक्षेप में, uint__ को परिभाषित करने के लिए एक C ++ मानक अनुरूप लाइब्रेरी की आवश्यकता नहीं है (टिप्पणी देखें / वैकल्पिक) )
संपूर्ण बिंदु कार्यान्वयन-स्वतंत्र कोड लिखना है। unsigned char
8-बिट प्रकार होने की गारंटी नहीं है। uint8_t
है (यदि उपलब्ध हो)।
sizeof(unsigned char)
लौटेगा 1
। लेकिन अगर एक सिस्टम चार और int का आकार समान है, उदाहरण के लिए, 16-बिट्स तो sizeof(int)
भी वापस आ जाएगी1
जैसा कि आपने कहा, " लगभग हर प्रणाली"।
char
शायद बदलने की कम संभावना में से एक है, लेकिन एक बार जब आप uint16_t
दोस्तों का उपयोग करना शुरू करते हैं , तो uint8_t
बेहतर मिश्रणों का उपयोग करते हैं , और यहां तक कि कोडन मानक का हिस्सा भी हो सकते हैं।
मेरे अनुभव में दो जगह हैं जहां हम 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
थोड़ा है। पोर्टेबिलिटी के दृष्टिकोण से, char
8 बिट्स से छोटा नहीं हो सकता है, और कुछ भी छोटा नहीं हो सकता है char
, इसलिए यदि किसी दिए गए सी कार्यान्वयन में एक अहस्ताक्षरित 8-बिट पूर्णांक प्रकार है, तो यह होने जा रहा है char
। वैकल्पिक रूप से, इसमें एक भी नहीं हो सकता है, जिस बिंदु पर कोई भी typedef
चाल चलनी है।
इसका उपयोग आपके कोड को इस अर्थ में बेहतर ढंग से करने के लिए किया जा सकता है कि यह स्पष्ट हो कि आपको वहां 8-बिट बाइट्स की आवश्यकता है और कुछ नहीं। लेकिन व्यवहार में यह एक वाजिब उम्मीद है कि वस्तुतः पहले से ही कहीं भी (डीएसपी प्लेटफ़ॉर्म हैं, जिस पर यह सच नहीं है, लेकिन आपके कोड के चलने की संभावना पतली है, और आप बस अपने प्रोग्राम के शीर्ष पर स्थैतिक मुखर का उपयोग करके त्रुटि कर सकते हैं। ऐसा मंच)।
unsigned char
0 और 255 के बीच मान रखने में सक्षम होना चाहिए । यदि आप ऐसा कर सकते हैं तो 4 बिट्स में, मेरी टोपी आपके पास है।
uint8_t
कार्यान्वयन में जोड़ें । मुझे आश्चर्य है, 16bit चार्ट के साथ डीएसपी के लिए कंपाइलर आमतौर पर लागू होते हैं uint8_t
, या नहीं?
#include <stdint.h>
और उपयोग करें uint8_t
। यदि प्लेटफ़ॉर्म के पास है, तो यह आपको दे देगा। यदि प्लेटफ़ॉर्म नहीं है, तो आपका प्रोग्राम संकलित नहीं होगा, और इसका कारण स्पष्ट और सीधा होगा।
यह वास्तव में उदाहरण के लिए महत्वपूर्ण है जब आप एक नेटवर्क विश्लेषक लिख रहे हैं। पैकेट हेडर को प्रोटोकॉल विनिर्देश द्वारा परिभाषित किया जाता है, न कि किसी विशेष प्लेटफॉर्म के सी कंपाइलर के काम करने के तरीके से।
लगभग हर प्रणाली पर मैं uint8_t == अहस्ताक्षरित चार से मिला हूं, लेकिन यह सी मानक द्वारा गारंटी नहीं है। यदि आप पोर्टेबल कोड लिखने की कोशिश कर रहे हैं और यह मायने रखता है कि मेमोरी किस आकार की है, तो uint8_t का उपयोग करें। अन्यथा अहस्ताक्षरित चार का उपयोग करें।
uint8_t
8-बिट unsigned char
होने पर हमेशा श्रेणी और पैडिंग का आकार (कोई नहीं) होता unsigned char
है। जब unsigned char
8-बिट uint8_t
नहीं है , तो मौजूद नहीं है।
unsigned char
8 बिट, है uint8_t
एक होने की गारंटी typedef
क्या है और नहीं एक typedef
एक की विस्तारित अहस्ताक्षरित पूर्णांक प्रकार ?
unsigned char/signed char/char
क्योंकि सबसे छोटे प्रकार हैं - 8 बिट से छोटा नहीं। unsigned char
कोई पैडिंग नहीं है। होने के uint8_t
लिए, यह 8-बिट्स होना चाहिए, कोई पैडिंग नहीं है, एक कार्यान्वयन प्रदान करने के कारण मौजूद है पूर्णांक प्रकार: न्यूनतम आवश्यकताओं का मिलान unsigned char
। जैसा कि "... एक टाइपराइफ़ होने की गारंटी है ..." पोस्ट करने के लिए एक अच्छा प्रश्न लगता है।