2012-03-23 16 views
37

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

  • 1:

    यह के लिए खोज रहे stackoverflow और अन्य लोगों साइटों पर, मैं 2 लिंक है कि विषय के बारे में व्यवहार करता है पाया।

  • 2 - यह uint8_t के बारे में अधिक विशिष्ट है।

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

तो, मेरा सवाल यह है कि वास्तव में विपक्ष क्या है, और विशेष रूप से पोर्टेबिलिटी के अलावा स्टिंट का उपयोग करने के पेशेवर, और मुझे इसका उपयोग करना चाहिए बस मेरे कोड के कुछ विनिर्देश भागों में, या हर जगह? यदि हर जगह, मैं उपयोगकर्ता के साथ atoi, strtok, आदि कैसे काम कर सकता हूं?

धन्यवाद!

उत्तर

57

पेशेवरों

अच्छी तरह से परिभाषित प्रकार का उपयोग करना, कोड काफी आसान और बंदरगाह के लिए सुरक्षित बनाता है। Stdint.h के साथ, आप जो भी टाइप करते हैं वह आपको मिलता है।

int आदि का उपयोग करना खतरनाक प्रकार के प्रचारों का पता लगाना मुश्किल बनाता है।

एक और फायदा यह है कि char के बजाय int8_t का उपयोग करके, आप जानते हैं कि आपको हमेशा एक हस्ताक्षरित 8 बिट चर मिलता है। char पर हस्ताक्षर या हस्ताक्षर किए जा सकते हैं, यह कार्यान्वयन-परिभाषित व्यवहार है और संकलक के बीच भिन्न होता है।इसलिए, डिफ़ॉल्ट char पोर्टेबल होना चाहिए कोड में उपयोग करने के लिए सादा खतरनाक है।

यदि आप उस चर के संकलक संकेतों को अनुकूलित करना चाहते हैं, तो आप uint_fastx_t का उपयोग कर सकते हैं जो संकलक को सबसे तेज़ संभव पूर्णांक प्रकार का उपयोग करने के लिए कहता है, कम से कम 'x' जितना बड़ा। अधिकांश समय इससे कोई फर्क नहीं पड़ता, कंपाइलर टाइप आकारों पर ऑप्टिमाइज़ेशन करने के लिए पर्याप्त स्मार्ट है, इससे कोई फर्क नहीं पड़ता कि आपने क्या टाइप किया है। अनुक्रम बिंदुओं के बीच, कंपाइलर निर्दिष्ट रूप से निर्दिष्ट प्रकार से दूसरे को बदल सकता है, जब तक कि यह परिणाम को प्रभावित नहीं करता है।

विपक्ष

कोई नहीं।


संदर्भ: मिश्रा सी:। 2004 नियम 6.3 "typedefs कि संकेत मिलता है आकार और signedness बुनियादी प्रकार के स्थान पर इस्तेमाल किया जाएगा"।

संपादित करें: गलत उदाहरण हटा दिया गया।

+3

वैलीक के रूप में स्पष्ट विपक्ष प्रदर्शन प्रभाव है। एक 12 बिट मशीन पर uint32_t पूर्णांक में गिनने के लिए मजबूर होना कठिन है – hroptatyr

+14

'uint32_t' 12 बिट मशीन पर मौजूद नहीं हो सकता है। –

+3

@hroptatyr यदि आप फिर से मेरा जवाब पढ़ते हैं, तो आप पाएंगे कि मैंने उस मुद्दे को संबोधित किया है। अगर इसे 'uint32_t' होना चाहिए, तो इसे इसके रूप में घोषित करें। यदि उसे उस उच्च रिज़ॉल्यूशन की आवश्यकता नहीं है, लेकिन केवल 16 बिट है, तो इसे 'uint_fast16_t' के रूप में घोषित करें, जिसे एक सीपीयू पर 32 बिट के रूप में संकलित किया जाएगा जहां 32 बिट संरेखण तेज है। – Lundin

7

विपक्ष

प्राथमिक कारण सी भाषा int या long, आदि के आकार को निर्दिष्ट नहीं करता कम्प्यूटेशनल दक्षता के लिए है। प्रत्येक वास्तुकला में एक प्राकृतिक, सबसे कुशल आकार होता है, और डिजाइनरों ने विशेष रूप से सशक्त और गतिशील और कोड आकार दक्षता के लिए प्राकृतिक देशी डेटा आकार डेटा का उपयोग करने के लिए संकलक कार्यान्वयन का इरादा किया है।

पिछले कुछ वर्षों में, अन्य मशीनों के साथ संचार प्राथमिक चिंता नहीं थी — अधिकांश कार्यक्रम मशीन — मशीन के लिए स्थानीय थे इसलिए प्रत्येक डेटा प्रकार के आकार की भविष्यवाणी कम चिंता का विषय था।

जोर देते हुए कि एक विशेष वास्तुकला किसी विशेष आकार int का उपयोग के साथ गिनती करने के लिए भले ही यह अन्य चीजों को आसान बनाने के लिए प्रतीत होता है एक बहुत बुरा विचार है।

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

+12

-1, आप मानक को नहीं जानते हैं। stdint.h में केवल 'uintx_t' नहीं है, बल्कि 'uintx_least_t' और' uintx_fast_t' भी शामिल है। साथ ही, कोड को पोर्ट करते समय आप अचानक प्रकार के आकार में बदलाव के साथ कोई आश्चर्य नहीं चाहते हैं। यदि पोर्टेबिलिटी महत्वपूर्ण है, तो कोड को उन प्रकारों का उपयोग करना चाहिए जो किसी भी मशीन पर अच्छी तरह से काम करेंगे। मैं बुनियादी स्टेडेंट प्रकारों का उपयोग करता हूं, न कि तेजी से, और अक्सर बिना किसी समस्या के छोटे 8-बिट एमसीयू और बोझिल 64-बिट पीसी के बीच जंगली रूप से बंदरगाह। जब मैं ऐसा करता हूं तो कोड को फिर से लिखना नहीं है, वास्तव में मुझे वास्तव में एक अच्छा विचार लगता है। – Lundin

+3

@ लंदन: 'int16_fast_t' जैसे प्रकार अधिक उपयोगी होंगे यदि मानक अनुमति देने वाले कंपाइलर्स ऐसे मामलों में अतिरिक्त सटीकता प्रदान करते हैं जहां यह हमेशा इसे देने के बिना अधिक कुशल होगा। कोड जो मेमोरी दक्षता (एम्बेडेड सिस्टम पर आम) में रूचि रखता है, बहुत भिन्न हो सकता है यदि एक चर की सीमा इस बात पर निर्भर हो सकती है कि क्या यह एक रजिस्टर में संग्रहीत किया गया था, भले ही कोई ऐसा नियम हो जो किसी विशेष चर की सीमा की आवश्यकता हो हर जगह वर्दी। इस तरह के नियम के तहत, 'int16_fast_t' कई मशीनों पर' int16_t' के रूप में कॉम्पैक्ट के रूप में हो सकता है ... – supercat

+3

... अभी भी सभी गति लाभ प्राप्त कर रहे हैं जिन्हें महसूस किया जा सकता है कि इसे 'int' में पदोन्नत किया गया था। – supercat

6

मैं केवल एक कारण के लिए stdint प्रकारों का उपयोग करता हूं, जब स्मृति में जो डेटा है, वह बाइनरी रूप में डिस्क/नेटवर्क/डिस्क्रिप्टर पर जाएगा। आपको केवल छोटे-एंडियन/बड़े-एंडियन मुद्दे से लड़ना है, लेकिन यह अपेक्षाकृत easy to overcome है।

स्पष्ट कारण stdint का उपयोग करने के लिए है जब कोड आकार-स्वतंत्र होता है, गणित में तर्कसंगत पूर्णांक पर काम करने वाली सभी चीजें होती हैं। * के प्रत्येक विस्तार के लिए, qsort() का कहना है कि यह uint*_t संस्करण प्रदान करता है, तो यह बदसूरत कोड डुप्लिकेट उत्पन्न करेगा।

मैं उस मामले में अपने स्वयं के प्रकार का उपयोग करता हूं, size_t से लिया गया है जब मैं आलसी हूं या मंच पर सबसे बड़ा समर्थित हस्ताक्षरित पूर्णांक नहीं हूं।

संपादित करें, क्योंकि मैं इस मुद्दे को पहले में भाग:
मुझे लगता है कि यह उल्लेखनीय है कि कम से कम uint8_t, uint32_t और uint64_t सोलारिस 2.5.1 में टूट रहे हैं। तो अधिकतम पोर्टेबिलिटी के लिए मैं अभी भी stdint.h (कम से कम अगले कुछ वर्षों के लिए) से बचने का सुझाव देता हूं।

16

uint8_t बजाय unsigned char (सौन्दर्य वरीयता को छोड़ कर) का उपयोग करने के एकमात्र कारण यदि आप दस्तावेज़ के लिए कि अपने कार्यक्रम char की आवश्यकता है वास्तव में 8 बिट होना चाहते है। uint8_t मौजूद है और केवल CHAR_BIT==8, सी मानक की आवश्यकताओं के अनुसार।

intX_t और uintX_t प्रकार के बाकी निम्न स्थितियों में उपयोगी होते हैं:

  • पढ़ने/लिखने के डिस्क/नेटवर्क (लेकिन फिर आप भी endian रूपांतरण कार्यों का उपयोग करने के लिए है)
  • आप अहस्ताक्षरित चाहते हैं जब एक सटीक कटऑफ पर रैपरराउंड व्यवहार (लेकिन यह & ऑपरेटर के साथ अधिक पोर्टेबल किया जा सकता है)।
  • जब आप किसी संरचना के सटीक लेआउट को नियंत्रित कर रहे हैं क्योंकि आपको यह सुनिश्चित करने की आवश्यकता है कि कोई पैडिंग मौजूद नहीं है (उदा। memcmp या हैशिंग उद्देश्यों के लिए)।

दूसरी ओर, uint_least8_t, आदि प्रकार के उपयोगी कहीं भी है कि आप wastefully बड़े या धीमी गति से प्रकार का उपयोग कर से बचने के लिए चाहते हैं, लेकिन यह सुनिश्चित करें कि आप एक निश्चित परिमाण के मान संग्रहीत कर सकते की जरूरत है। उदाहरण के लिए, long long कम से कम 64 बिट्स है, लेकिन यह कुछ मशीनों पर 128-बिट हो सकता है, और जब आपको आवश्यकता हो तो इसका उपयोग करना एक प्रकार है जो 64 बिट नंबरों को स्टोर कर सकता है, ऐसी मशीनों पर बहुत अपमानजनक होगा। int_least64_t समस्या हल करता है।

मैं पूरी तरह [u]int_fastX_t प्रकार का उपयोग कर, क्योंकि वे है से बचने के हैं कभी कभी एक दिया मशीन (एबीआई तोड़ने) पर बदल गया है और के बाद से परिभाषाएँ आमतौर पर गलत हैं। उदाहरण के लिए, x86_64 पर, 64-बिट पूर्णांक प्रकार को 16-, 32-, और 64-बिट मानों के लिए "तेज़" माना जाता है, लेकिन अतिरिक्त, घटाव और गुणा एक ही गति है, चाहे आप 32- बिट या 64-बिट मान, विभाजन लगभग आवश्यक प्रकारों के साथ लगभग निश्चित रूप से धीमा है, और यहां तक ​​कि यदि वे एक ही गति थे, तो आप बिना किसी लाभ के स्मृति को दो बार उपयोग कर रहे हैं।

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

+2

int_fastx_t के साथ समस्या प्रोग्रामर को स्वयं से चिंता करने की आवश्यकता होने के बजाय, एक कंपाइलर बग की तरह लगता है। और मैं मानता हूं कि अधिकांश मामलों में काउंटर वैरिएबल (लूप इंट इंटरैटर आदि के लिए) आकार_टी होना चाहिए। – Lundin

+0

"डिस्क/नेटवर्क पढ़ने/लिखना" पीसी जवाब है। आपको निश्चित रूप से किसी भी प्रकार के एम्बेडेड सिस्टम में स्टिंट प्रकार की आवश्यकता होती है, जहां आप हार्डवेयर रजिस्टरों, डायरेक्ट मेमोरी एक्सेस, मेमोरी हैंडलिंग रूटीन, डेटा प्रोटोकॉल मैपिंग्स, इंटरप्ट वेक्टर सेटअप, बूटलोडर्स ... और इसी तरह से काम कर रहे हैं। – Lundin

+0

@ लुंडिन: तथ्य यह है कि यह एक व्यापक "बग" है, साथ ही पीएसएबीआई में इन प्रकार की परिभाषाओं के लिए एक विनिर्देश की कमी के साथ, प्रोग्रामर के लिए चिंतित होने के लिए ** बहुत अच्छा ** कारण है। इसका मतलब है कि अगर बग कभी तय किया जाता है, तो इन प्रकारों का उपयोग करने वाले बाहरी इंटरफेस एबीआई संगतता को तोड़ देंगे। इससे भी बदतर, आपके इंटरफेस का "संस्करण" आपके पुस्तकालय संस्करण द्वारा नहीं बल्कि आपके कंपाइलर संस्करण द्वारा निर्धारित किया जाता है। –

संबंधित मुद्दे

 संबंधित मुद्दे