Uint_fast32_t के बजाय uint32_t को क्यों प्राथमिकता दी जाएगी?


82

ऐसा लगता है कि uint32_tइसकी तुलना में बहुत अधिक प्रचलित है uint_fast32_t(मुझे लगता है कि यह वास्तविक प्रमाण है)। यह मेरे लिए काउंटर-सहज ज्ञान युक्त लगता है, हालांकि।

लगभग हमेशा जब मैं एक कार्यान्वयन उपयोग देखता हूं uint32_t, तो यह वास्तव में चाहता है कि एक पूर्णांक है जो 4,294,967,295 तक मूल्यों को धारण कर सकता है (आमतौर पर 65,535 और 4,294,967,295 के बीच कहीं बहुत कम बाध्य)।

यह तब उपयोग करने के लिए अजीब लगता है uint32_t, क्योंकि 'बिल्कुल 32 बिट्स' की गारंटी की आवश्यकता नहीं है, और 'सबसे तेज उपलब्ध> = 32 बिट्स' की गारंटी uint_fast32_tबिल्कुल सही विचार प्रतीत होती है। इसके अलावा, जबकि यह आमतौर पर लागू किया जाता है, uint32_tवास्तव में मौजूद होने की गारंटी नहीं है।

फिर, क्यों uint32_tपसंद किया जाएगा? क्या यह केवल बेहतर ज्ञात है या दूसरे पर तकनीकी फायदे हैं?


24
सरल उत्तर, हो सकता है कि उन्हें एक पूर्णांक की आवश्यकता हो जो कि वास्तव में 32 बिट है?
स्टारगेटर

7
पहले मैंने सुना है uint32_fast_t, जो अगर मैं सही ढंग से समझ रहा हूं, तो कम से कम 32 बिट्स हैं (मतलब यह अधिक हो सकता है? मेरे लिए भ्रामक लगता है)। मैं वर्तमान में uint32_tअपने प्रोजेक्ट पर उपयोग कर रहा हूं और दोस्तों क्योंकि मैं इस डेटा को पैक कर रहा हूं और इसे नेटवर्क पर भेज रहा हूं, और मैं प्रेषक और रिसीवर को यह जानना चाहता हूं कि वास्तव में क्षेत्र कितने बड़े हैं। ऐसा लगता है कि सबसे मजबूत समाधान नहीं हो सकता है क्योंकि एक मंच लागू नहीं हो सकता है uint32_t, लेकिन मेरा सभी स्पष्ट रूप से करते हैं इसलिए मैं जो कर रहा हूं उसके साथ ठीक हूं।
यानो

5
@yano: नेटवर्किंग के लिए, आपको बाइट ऑर्डर / एंडियनस के बारे में भी ध्यान रखना चाहिए - आपको uint32_tवह नहीं देता (और यह एक दया है कि नहीं uint32_t_beऔर uint32_t_le, जो लगभग हर संभव मामले के लिए अधिक उपयुक्त होगा जहां uint32_tवर्तमान में सबसे अच्छा विकल्प है)।
ब्रेंडन

3
@Brendan - _be और _le के संबंध में, क्या htonl () और ntohl () एक ही क्षमता प्रदान करेंगे?
mpez0

2
@ बेंडन जो कि एक मानक हैड में छुपाने के लिए एक बहुत भारी वस्तु है जो सभी आदिम प्रकार के होते हैं। मैं इस सिद्धांत से आपसे सहमत हूँ कि इसे कहीं मानक में संभाला जाना चाहिए लेकिन मुझे लगता है कि यह स्थान नहीं हो सकता है
स्टीव कॉक्स

जवाबों:


79

uint32_tकिसी भी प्लेटफ़ॉर्म पर इसका समर्थन करने वाले लगभग समान गुण होने की गारंटी है। 1

uint_fast32_t इसकी तुलना में विभिन्न प्रणालियों पर यह कैसे व्यवहार करता है, इसकी बहुत कम गारंटी है।

यदि आप एक ऐसे प्लेटफ़ॉर्म पर जाते हैं जहाँ uint_fast32_tएक अलग आकार है, तो उपयोग uint_fast32_tकरने वाले सभी कोड को रिटायर्ड और मान्य किया जाना है। सभी स्थिरता धारणाएं खिड़की से बाहर होने वाली हैं। पूरा सिस्टम अलग तरह से काम करने वाला है।

जब आपके कोड लिखने, तुम भी नहीं हो सकता है पहुँच एक करने के लिए uint_fast32_tप्रणाली है कि आकार में 32 बिट नहीं है।

uint32_t अलग तरह से काम नहीं करेगा (फुटनोट देखें)।

गति की तुलना में सुधार अधिक महत्वपूर्ण है। इस प्रकार समय से पहले अनुकूलन की तुलना में समयपूर्व शुद्धता एक बेहतर योजना है।

ऐसी स्थिति में, मैं उन प्रणालियों के लिए कोड लिख रहा था जहां uint_fast32_t64 या अधिक बिट्स थे, मैं दोनों मामलों के लिए अपने कोड का परीक्षण कर सकता हूं और इसका उपयोग कर सकता हूं। जरूरत और अवसर दोनों को छोड़कर, ऐसा करना एक बुरी योजना है।

अंत में, uint_fast32_tजब आप इसे किसी भी लम्बाई के लिए संग्रहीत कर रहे हैं या उदाहरणों की संख्या uint32कैश आकार के मुद्दों और मेमोरी बैंडविड्थ की वजह से धीमी हो सकती है । टॉड्स कंप्यूटर सीपीयू बाउंड की तुलना में अधिक बार मेमोरी-बाउंड होते हैं, और uint_fast32_tअलगाव में तेज हो सकते हैं लेकिन मेमोरी ओवरहेड के लिए आपके खाते में नहीं होने के बाद।


1 जैसा कि @chux ने टिप्पणी में उल्लेख किया है, यदि अंकगणित सामान्य से unsignedअधिक है uint32_t, तो अंकगणितीय uint32_tसामान्य पूर्णांक प्रचार के माध्यम से जाता है, और यदि नहीं, तो यह इस प्रकार रहता है uint32_t। इससे कीड़े हो सकते हैं। कुछ भी कभी भी सही नहीं है।


15
"uint32_t को किसी भी मंच पर समान गुण होने की गारंटी है जो इसका समर्थन करता है।" एक कोने की समस्या है जब unsignedव्यापक से अधिक है uint32_tऔर फिर uint32_tएक मंच पर सामान्य पूर्णांक प्रचार के माध्यम से चला जाता है और दूसरे पर ऐसा नहीं होता है। फिर भी uint32_tइन पूर्णांक गणित के साथ समस्या काफी कम हो जाती है।
chux -

2
@ एक कोने का मामला जो गुणा करते समय UB का कारण बन सकता है, क्योंकि पदोन्नति पसंद किए गए int और हस्ताक्षरित पूर्णांक अतिप्रवाह UB है।
कोडइन्चोस

2
यद्यपि यह उत्तर सही है जहाँ तक यह जाता है, यह मुख्य विवरण को बहुत कम करता है। संक्षेप में, uint32_tवह जगह है जहां मशीन के प्रकार का सटीक विवरण महत्वपूर्ण है, जबकि uint_fast32_tइसके लिए जहां कम्प्यूटेशनल गति सबसे महत्वपूर्ण है, (संयुक्त राष्ट्र) हस्ताक्षर और न्यूनतम सीमा महत्वपूर्ण है, और प्रतिनिधित्व का विवरण गैर-आवश्यक है। वहाँ भी uint_least32_tहै जहाँ (संयुक्त राष्ट्र) के लिए हस्ताक्षर और न्यूनतम सीमा सबसे महत्वपूर्ण है, कॉम्पैक्टनेस गति से अधिक महत्वपूर्ण है, और सटीक प्रतिनिधित्व आवश्यक नहीं है।
जॉन बोलिंगर

@ जॉनबोलिंगर जो सभी अच्छी तरह से और अच्छा है, लेकिन वास्तविक हार्डवेयर पर परीक्षण किए बिना जो 1 से अधिक प्रकारों को लागू करता है, चर आकार के प्रकार एक जाल हैं। और इसका कारण यह है कि लोग uint32_tअन्य प्रकारों के बजाय उपयोग करते हैं क्योंकि उनके पास आमतौर पर परीक्षण करने के लिए ऐसे हार्डवेयर नहीं होते हैं । (समान का सच है int32_tकुछ हद तक, और यहां तक कि intऔर short)।
यक्क - एडम नेवरामोंट

1
कोने के मामले का एक उदाहरण: Let unsigned short== uint32_tऔर int== int48_t। यदि आप कुछ इस तरह की गणना करते हैं (uint32_t)0xFFFFFFFF * (uint32_t)0xFFFFFFFF, तो ऑपरेंड को बढ़ावा दिया जाता है signed intऔर एक हस्ताक्षरित पूर्णांक अतिप्रवाह को ट्रिगर करेगा, जो अपरिभाषित व्यवहार है। इस प्रश्न को देखें।
नायुकी

32

कई लोग uint32_tइसके बजाय क्यों इस्तेमाल करते हैं uint32_fast_t?

नोट: मिस-नाम uint32_fast_tहोना चाहिए uint_fast32_t

uint32_tकी तुलना में अधिक विशिष्ट uint_fast32_tकार्यक्षमता के लिए एक सख्त विनिर्देश है ।


uint32_t पेशेवरों:

  • विभिन्न एल्गोरिदम इस प्रकार को निर्दिष्ट करते हैं। IMO - उपयोग करने का सर्वोत्तम कारण।
  • सटीक चौड़ाई और सीमा ज्ञात है।
  • इस प्रकार की किरणें बेकार नहीं जाती हैं।
  • अहस्ताक्षरित पूर्णांक गणित अपने अतिप्रवाह के साथ अधिक अनुमानित है।
  • अन्य भाषाओं के 32-बिट प्रकारों की सीमा और गणित में निकटता का मिलान होता है।
  • कभी गद्देदार नहीं।

uint32_t विपक्ष:

  • हमेशा उपलब्ध नहीं (फिर भी यह 2018 में दुर्लभ है)।
    जैसे: प्लेटफ़ॉर्म में 8/16/32-बिट पूर्णांक (9/18/ 36- बिट, अन्य ) का अभाव है ।
    उदा: गैर-2 के पूरक का उपयोग करके प्लेटफ़ॉर्म। पुराना 2200

uint_fast32_t पेशेवरों:

  • हमेशा उपलब्ध।
    यह हमेशा सभी प्लेटफार्मों, नए और पुराने, को तेज / न्यूनतम प्रकार का उपयोग करने की अनुमति देता है।
  • "सबसे तेज़" प्रकार जो 32-बिट श्रेणी का समर्थन करता है।

uint_fast32_t विपक्ष:

  • रेंज केवल न्यूनतम रूप से ज्ञात है। उदाहरण, यह 64-बिट प्रकार हो सकता है।
  • इस प्रकार की सरणियाँ स्मृति में बेकार हो सकती हैं।
  • सभी उत्तर (मेरा भी सबसे पहले), पोस्ट और टिप्पणियों ने गलत नाम का उपयोग किया uint32_fast_t। लगता है जैसे कई की जरूरत नहीं है और इस प्रकार का उपयोग करें। हम भी सही नाम का उपयोग नहीं किया!
  • गद्दी संभव - (दुर्लभ)।
  • चुनिंदा मामलों में, "सबसे तेज़" प्रकार वास्तव में एक अन्य प्रकार हो सकता है। तो uint_fast32_tकेवल 1 ऑर्डर सन्निकटन है।

अंत में, जो सबसे अच्छा है वह कोडिंग लक्ष्य पर निर्भर करता है। जब तक कि बहुत व्यापक पोर्टेबिलिटी या कुछ niched प्रदर्शन फ़ंक्शन के लिए कोडिंग न करें, उपयोग करें uint32_t


इन प्रकारों का उपयोग करते समय एक और मुद्दा है जो खेल में आता है: उनकी रैंक की तुलना में int/unsigned

संभवतः uint_fastN_tकी रैंक हो सकती है unsigned। यह निर्दिष्ट नहीं है, लेकिन एक निश्चित और परीक्षण योग्य स्थिति है।

इस प्रकार, संकीर्ण uintN_tहोने की तुलना में अधिक संभावना है । इसका मतलब यह है कि कोड जो गणित का उपयोग करता है, जब पोर्टेबिलिटी के संबंध में पूर्णांक पदोन्नति के अधीन होने की संभावना है।uint_fastN_tunsigneduintN_tuint_fastN_t

इस चिंता के साथ: uint_fastN_tचुनिंदा गणित संचालन के साथ पोर्टेबिलिटी लाभ ।


इसके int32_tबजाय साइड नोट int_fast32_t: दुर्लभ मशीनों पर, INT_FAST32_MIN-2,147,483,647 हो सकता है और -2,147,483,648 नहीं हो सकता है। बड़ा बिंदु: (u)intN_tप्रकार कसकर निर्दिष्ट होते हैं और पोर्टेबल कोड तक ले जाते हैं।


2
सबसे तेज़ प्रकार जो 32-बिट श्रेणी => वास्तव में समर्थन करता है ? यह ऐसे समय का एक अवशेष है जब RAM CPU गति पर चल रहा था, आजकल संतुलन पीसी पर नाटकीय रूप से स्थानांतरित हो गया है इसलिए (1) मेमोरी से 32-बिट पूर्णांक खींचना 64-बिट्स को खींचने के रूप में दोगुना है और (2) सदिश निर्देश 32-बिट पूर्णांक दो बार क्रंच करते हैं, जितना वे 64-बिट्स पर करते हैं। क्या यह अभी भी सबसे तेज है?
Matthieu M.

4
कुछ चीजों के लिए सबसे तेज, दूसरी चीजों के लिए धीमी। जब आप सरणियों को शून्य-विस्तार की आवश्यकता समझते हैं, तो "कोई भी पूर्णांक का सबसे तेज़ आकार" क्या होता है, इसका कोई एक आकार-फिट-उत्तर नहीं है। X86-64 सिस्टम V ABI में, uint32_fast_t64-बिट प्रकार है, इसलिए यह कभी-कभी साइन-एक्सटेंशन को बचाता है और imul rax, [mem]64-बिट पूर्णांक या पॉइंटर्स के साथ इसका उपयोग करते समय एक अलग शून्य-विस्तार लोड निर्देश के बजाय अनुमति देता है । लेकिन यह सब आपको कैश फ़ुटप्रिंट और अतिरिक्त कोड-साइज़ के डबल करने की कीमत के लिए मिलता है (आरईएक्स सब कुछ पर उपसर्ग करता है।)
पीटर कॉर्डेस

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

2
मुझे उम्मीद है कि सभी C और C ++ अनुप्रयोगों पर भारित औसत के रूप में, uint32_fast_tx86 पर बनाना एक भयानक विकल्प है। कार्य है कि तेजी से कर रहे हैं कुछ और दूर के बीच हैं, और लाभ जब वे होते हैं ज्यादातर मामूली हैं: के लिए मतभेद imul rax, [mem]मामले कि @PeterCordes का उल्लेख कर रहे हैं बहुत , बहुत छोटे: जुड़े हुए डोमेन और unfused डोमेन शून्य में एक भी UOP। अधिकांश दिलचस्प परिदृश्यों में यह एक चक्र भी नहीं जोड़ेगा। शेष राशि जो डबल मेमोरी मेमोरी और बदतर वेक्टराइजेशन के खिलाफ है , इसे बहुत बार जीतते हुए देखना मुश्किल है।
BeeOnRope

2
@PeterCordes - दिलचस्प लेकिन यह भी भयानक :)। यह fast_tएक और भी बदतर बना देगा int: न केवल अलग-अलग प्लेटफार्मों पर इसके अलग-अलग आकार होते हैं, बल्कि अलग-अलग आकार होंगे जो अनुकूलन के निर्णय और अलग-अलग फ़ाइलों में अलग-अलग आकार के आधार पर होंगे! एक व्यावहारिक मामले के रूप में, मुझे लगता है कि यह पूरे कार्यक्रम के अनुकूलन के साथ भी काम नहीं कर सकता है: C और C ++ में आकार तय किए गए हैं sizeof(uint32_fast_t)या ऐसा कुछ भी जो इसे सीधे निर्धारित करता है, हमेशा एक ही मूल्य वापस करना है, इसलिए यह कंपाइलर के लिए बहुत कठिन होगा। ऐसा परिवर्तन करें।
BeeOnRope

25

कई लोग uint32_tइसके बजाय क्यों इस्तेमाल करते हैं uint32_fast_t?

मूर्खतापूर्ण उत्तर:

  • कोई मानक प्रकार नहीं है uint32_fast_t, सही वर्तनी है uint_fast32_t

व्यावहारिक उत्तर:

  • कई लोग वास्तव में uint32_tया int32_tअपने सटीक शब्दार्थ के लिए उपयोग करते हैं , अंकगणित ( uint32_t) या 2 के पूरक प्रतिनिधित्व ( int32_t) के आसपास अहस्ताक्षरित आवरण के साथ बिल्कुल 32 बिट्स । xxx_fast32_tप्रकार बड़ा है और इस तरह से पैक सरणियों और संरचनाओं में बाइनरी फ़ाइलें, उपयोग करने के लिए दुकान करने के लिए अनुपयुक्त हो, या एक नेटवर्क पर भेज सकते हैं। इसके अलावा, वे भी तेज नहीं हो सकता है।

व्यावहारिक जवाब:

  • बहुत से लोग केवल uint_fast32_tटिप्पणियों के बारे में नहीं जानते (या बस परवाह नहीं करते हैं) , जैसा कि टिप्पणियों और उत्तरों में दिखाया गया है, और संभवतः unsigned intसमान शब्दार्थ रखने के लिए सादे मानते हैं , हालांकि कई वर्तमान आर्किटेक्चर में अभी भी 16-बिट intएस और कुछ दुर्लभ संग्रहालय के नमूने हैं 32 से कम अन्य अजीब अंतर आकार।

UX उत्तर:

  • यद्यपि संभवतः इससे अधिक तेज़ uint32_t, uint_fast32_tउपयोग करने के लिए धीमा है: यह टाइप करने में अधिक समय लेता है, विशेष रूप से सी दस्तावेज में वर्तनी और शब्दार्थ देखने के लिए लेखांकन; ;-)

लालित्य मायने रखता है, (जाहिर तौर पर राय आधारित):

  • uint32_tबहुत बुरा लग रहा है कि कई प्रोग्रामर अपने स्वयं के u32या uint32प्रकार को परिभाषित करना पसंद करते हैं ... इस दृष्टिकोण से, uint_fast32_tमरम्मत से परे अनाड़ी दिखता है। कोई आश्चर्य नहीं कि यह अपने दोस्तों uint_least32_tऔर ऐसे बेंच पर बैठता है ।

UX के लिए +1। यह std::reference_wrapperमेरे अनुमान से बेहतर है , लेकिन कभी-कभी मुझे आश्चर्य होता है कि क्या मानक समिति वास्तव में यह चाहती है कि इसका उपयोग करने के लिए मानकीकृत प्रकार ...
Matthieu M.

7

एक कारण यह है कि unsigned intपहले से ही "सबसे तेज" बिना किसी विशेष टाइपराइफ की आवश्यकता के या किसी चीज़ को शामिल करने की आवश्यकता है। इसलिए, यदि आपको इसकी आवश्यकता है, तो बस मौलिक intया unsigned intप्रकार का उपयोग करें ।
हालांकि मानक स्पष्ट रूप से यह गारंटी नहीं देता है कि यह सबसे तेज़ है, यह अप्रत्यक्ष रूप से ऐसा करता है कि "सादे वातावरण में निष्पादन पर्यावरण की वास्तुकला द्वारा सुझाए गए प्राकृतिक आकार" 3.9.1 है। दूसरे शब्दों में, int(या इसके अहस्ताक्षरित समकक्ष) वह है जो प्रोसेसर के साथ सबसे अधिक आरामदायक है।

अब निश्चित रूप से, आप नहीं जानते कि आकार क्या unsigned intहो सकता है। आप केवल यह जानते हैं कि यह कम से कम उतना बड़ा है short(और मुझे याद है कि shortकम से कम 16 बिट्स होने चाहिए, हालांकि मुझे यह अब मानक में नहीं मिल सकता है!)। आमतौर पर यह सिर्फ सादा 4 बाइट्स का है, लेकिन यह सिद्धांत में बड़ा हो सकता है, या चरम मामलों में, यहां तक ​​कि छोटे ( हालांकि मैंने व्यक्तिगत रूप से कभी भी एक वास्तुकला का सामना नहीं किया है जहां यह मामला था, 1980 के दशक में 8-बिट कंप्यूटर पर भी नहीं। .. शायद कुछ माइक्रोकंट्रोलर, जो जानते हैं कि मैं डिमेंशिया से पीड़ित हूं, intतब 16 बिट्स स्पष्ट रूप से वापस आ गए थे)।

सी ++ मानक यह निर्दिष्ट करने के लिए परेशान नहीं करता है कि <cstdint>प्रकार क्या हैं या वे क्या गारंटी देते हैं, यह केवल "सी के समान" का उल्लेख करता है।

uint32_t, सी मानक के अनुसार, गारंटी देता है कि आपको 32 बिट्स मिलते हैं। कुछ अलग नहीं, कोई कम नहीं और कोई पैडिंग बिट्स नहीं। कभी-कभी यह वही है जो आपको चाहिए, और इस प्रकार यह बहुत मूल्यवान है।

uint_least32_tगारंटी देता है कि जो भी आकार है, वह 32 बिट्स से छोटा नहीं हो सकता है (लेकिन यह बहुत अच्छी तरह से बड़ा हो सकता है)। कभी-कभी, लेकिन एक सटीक विटध या "परवाह न करें" की तुलना में बहुत अधिक शायद ही, यही आप चाहते हैं।

अंत में, uint_fast32_tप्रलेखन-इरादे के उद्देश्यों को छोड़कर, मेरी राय में कुछ हद तक बहुत ही कम है। C मानक बताता है "एक पूर्णांक प्रकार को नामित करता है जो आमतौर पर सबसे तेज़ होता है" (शब्द "आमतौर पर" पर ध्यान दें) और स्पष्ट रूप से उल्लेख करता है कि इसे सभी उद्देश्यों के लिए सबसे तेज़ नहीं होना चाहिए। दूसरे शब्दों में, uint_fast32_tबस उसी के बारे में है uint_least32_t, जो आमतौर पर सबसे तेज़ है, केवल कोई गारंटी नहीं दी गई है (लेकिन कोई गारंटी नहीं है)।

चूंकि अधिकांश समय आप या तो सटीक आकार के बारे में परवाह नहीं करते हैं या आप बिल्कुल 32 (या 64, कभी-कभी 16) बिट्स चाहते हैं, और चूंकि "परवाह नहीं करते" unsigned intप्रकार वैसे भी सबसे तेज़ है, यह बताता है कि uint_fast32_tऐसा क्यों नहीं है प्रायः इस्तेमाल किया जाने वाला।


3
मुझे आश्चर्य है कि आपको int8-बिट प्रोसेसर पर 16-बिट याद नहीं है , मैं उन दिनों से किसी को भी याद नहीं कर सकता हूं जो कुछ भी बड़ा इस्तेमाल करते थे। यदि स्मृति कार्य करती है, तो खंडित x86 आर्किटेक्चर के लिए संकलक 16-बिट का उपयोग करते हैं int
मार्क रैनसम

@MarkRansom: वाह, आप सही हैं। मैं sooooo आश्वस्त intथा कि 68000 पर 32 बिट्स थे (जो मैंने एक उदाहरण के रूप में सोचा था)। यह नहीं था ...
डैमन

int16 बिट्स की न्यूनतम चौड़ाई के साथ अतीत में सबसे तेज़ प्रकार का होना था (यही कारण है कि सी में पूर्णांक पदोन्नति नियम है), लेकिन आज 64-बिट आर्किटेक्चर के साथ यह अब सच नहीं है। उदाहरण के लिए 8 बाइट पूर्णांक x86_64 बिट पर 4 बाइट पूर्णांकों से अधिक तेज़ होते हैं क्योंकि 4 बाइट पूर्णांक संकलक के साथ अतिरिक्त निर्देश सम्मिलित करना होता है जो 4 बाइट मान को 8 बाइट मानों के साथ तुलना करने से पहले 8 बाइट मान में विस्तारित करता है।
स्टेसीगर्ल

"अहस्ताक्षरित int" आवश्यक रूप से x64 पर सबसे तेज़ नहीं है। अजीब बातें हुईं।
जोशुआ

एक और सामान्य मामला यह है कि long, ऐतिहासिक कारणों से, 32-बिट होने की आवश्यकता है, और intअब किसी से अधिक व्यापक होने की आवश्यकता नहीं है long, इसलिए int64 बिट्स तेज होने पर भी 32-बिट रहने की आवश्यकता हो सकती है।
डेविसलर

6

मैंने ऐसे सबूत नहीं देखे हैं जो इसकी सीमा के uint32_tलिए इस्तेमाल किए जाते हैं । इसके बजाय, अधिकांश समय जो मैंने किया है देखा uint32_tहै का उपयोग किया जाता है, यह गारंटीकृत आवरण और बदलाव शब्दार्थ के साथ विभिन्न एल्गोरिदम में डेटा के 4 ऑक्टेट को रखने के लिए है!

uint32_tइसके बजाय उपयोग करने के अन्य कारण भी हैं uint_fast32_t: अक्सर यह है कि यह स्थिर एबीआई प्रदान करेगा। इसके अतिरिक्त मेमोरी उपयोग को सटीक रूप से जाना जा सकता है। यह बहुत अधिक ऑफसेट जो भी गति लाभ से होगा uint_fast32_t, जब भी उस प्रकार से अलग होगा uint32_t

मानों <65536 के लिए, पहले से ही एक आसान प्रकार है, इसे कहा जाता है unsigned int( unsigned shortकम से कम उस सीमा के रूप में अच्छी तरह से आवश्यक है, लेकिन unsigned intमूल शब्द आकार का है) मानों के लिए <4294967296, एक और कहा जाता है unsigned long


और अंत में, लोग उपयोग नहीं करते हैं uint_fast32_tक्योंकि यह झुंझलाहट लंबे समय तक टाइप करना और गलत करना आसान है: डी


@ikegami: आपने shortसंपादन के साथ मेरा इरादा बदल दिया है । intसंभवतया यह एक ऐसा व्रत है जो इससे अलग है short
एंटी हापला

1
आपका अंतिम वाक्य पूरी तरह से गलत है, फिर। यह दावा करना कि आपको संकलक की तुलना में बेहतर जानने के लिए आपके द्वारा दावा किए जाने वाले साधनों के unsigned intबजाय उपयोग करना चाहिए uint16_fast_t
इकेगामी

साथ ही, आपके पाठ के इरादे को बदलने के लिए मेरी क्षमा याचना। यह मेरा इरादा नहीं था।
इकेगामी

unsigned longयदि आपके प्लेटफ़ॉर्म में 64-बिट longs है और आपको केवल नंबरों की आवश्यकता है, तो एक अच्छा विकल्प नहीं है <2^32
रुस्लान

1
@ikegami: "अहस्ताक्षरित int" हमेशा पदोन्नत होने पर भी एक अहस्ताक्षरित प्रकार के रूप में व्यवहार करेगा। इस संबंध में यह दोनों से बेहतर है uint16_tऔर uint_fast16_t। यदि uint_fast16_tसामान्य पूर्णांक प्रकारों की तुलना में अधिक सीमित रूप से निर्दिष्ट किया गया हो, तो इसकी सीमा को उन वस्तुओं के अनुरूप नहीं होना चाहिए जिनके पते नहीं लिए गए हैं, जो प्लेटफार्मों पर कुछ प्रदर्शन लाभ प्रदान कर सकते हैं जो 32-बिट अंकगणितीय आंतरिक रूप से प्रदर्शन करते हैं, लेकिन 16-बिट डेटा बस है । हालाँकि मानक ऐसे लचीलेपन की अनुमति नहीं देता है।
सुपरकट

5

कई कारण।

  1. बहुत से लोग नहीं जानते कि 'तेज' प्रकार मौजूद हैं।
  2. यह टाइप करने के लिए अधिक क्रिया है।
  3. जब आप प्रकार के वास्तविक आकार को नहीं जानते हैं तो अपने कार्यक्रमों के व्यवहार के बारे में जानना कठिन है।
  4. मानक वास्तव में सबसे तेजी से पिन नहीं करता है, और न ही यह वास्तव में किस प्रकार का सबसे तेज है, बहुत संदर्भ निर्भर हो सकता है।
  5. मैंने अपने प्लेटफ़ॉर्म को परिभाषित करते समय प्लेटफ़ॉर्म डेवलपर्स का कोई भी विचार इन प्रकारों के आकार में नहीं देखा है। उदाहरण के लिए x86-64 लिनक्स पर "फास्ट" प्रकार के सभी 64-बिट हैं, भले ही x86-64 में 32-बिट मूल्यों पर तेज संचालन के लिए हार्डवेयर समर्थन हो।

सारांश में "तेज" प्रकार बेकार कचरा हैं। यदि आपको वास्तव में यह पता लगाने की आवश्यकता है कि किसी दिए गए एप्लिकेशन के लिए कौन सा प्रकार सबसे तेज़ है तो आपको अपने कोड को अपने कंपाइलर पर बेंचमार्क करना होगा।


ऐतिहासिक रूप से ऐसे प्रोसेसर रहे हैं जिनमें 32-बिट और / या 64-बिट मेमोरी एक्सेस निर्देश थे, लेकिन 8- & 16-बिट नहीं थे। तो int_fast {8,16} _t 20+ साल पहले बिल्कुल-नहीं-बेवकूफ था। AFAIK अंतिम ऐसा मुख्य प्रोसेसर था जो मूल DEC अल्फा 21064 (दूसरी पीढ़ी के 21164 में सुधार हुआ) था। संभवतः अभी भी एम्बेडेड डीएसपी या जो कुछ भी केवल शब्द एक्सेस करते हैं, लेकिन पोर्टेबिलिटी आमतौर पर ऐसी चीजों पर बहुत चिंता नहीं है, इसलिए मैं यह नहीं देखता कि आप उन पर कार्गो- व्रत क्यों रखते हैं। और हाथ से निर्मित क्रे थे "सब कुछ 64-बिट" मशीनें हैं।
user1998586

1
श्रेणी 1 बी: बहुत से लोग इस बात की परवाह नहीं करते हैं कि 'तेज' प्रकार मौजूद हैं। वह मेरी श्रेणी है।
gnasher729

श्रेणी 6: बहुत से लोग इस बात पर भरोसा नहीं करते हैं कि 'तेज' प्रकार सबसे तेज हैं। मैं उस श्रेणी में आता हूं।
स्पष्ट

5

शुद्धता और कोडिंग में आसानी के दृष्टिकोण से, विशेष रूप से अधिक सटीक परिभाषित आकार और अंकगणितीय शब्दार्थ के कारण uint32_tकई फायदे हैं uint_fast32_t, जैसा कि ऊपर दिए गए कई उपयोगकर्ताओं ने बताया है।

शायद जो याद किया गया है वह यह है कि इसका एक फायदा है uint_fast32_t- कि यह तेज हो सकता है , बस किसी भी सार्थक तरीके से कभी भी भौतिक नहीं होगा। 64-बिट प्रोसेसर में से अधिकांश जो 64-बिट युग (x86-64 और Aarch64 ज्यादातर) पर हावी हैं, 32-बिट आर्किटेक्चर से विकसित हुए हैं और 64-बिट मोड में भी तेजी से 32-बिट देशी ऑपरेशन हैं। तो uint_fast32_tबस uint32_tउन प्लेटफार्मों पर के रूप में ही है।

यहां तक ​​कि अगर पावर, MIPS64, SPARC जैसे "रन" में से कुछ भी केवल 64-बिट ALU ऑपरेशंस की पेशकश करते हैं, तो 32-बिट्स के दिलचस्प 32 बिट्स के विशाल संचालन को 64-बिट रजिस्टरों पर ठीक किया जा सकता है: नीचे 32-बिट होगा वांछित परिणाम (और सभी मुख्यधारा के प्लेटफॉर्म कम से कम आपको 32-बिट लोड / स्टोर करने की अनुमति देते हैं)। लेफ्ट शिफ्ट मुख्य समस्याग्रस्त है, लेकिन यहां तक ​​कि कंपाइलर में मूल्य / श्रेणी ट्रैकिंग अनुकूलन द्वारा कई मामलों में अनुकूलित किया जा सकता है।

मुझे संदेह है कि कभी-कभार थोड़ी धीमी बायीं पारी या 32x32 -> 64 गुणा ऐसे मूल्यों के लिए मेमोरी उपयोग को दोगुना करने जा रहा है , लेकिन सभी अस्पष्ट अनुप्रयोगों में।

अंत में, मैं यह नोट करूँगा कि जबकि ट्रेडऑफ़ को मोटे तौर पर "मेमोरी उपयोग और वेक्टराइज़ेशन पोटेंशिअल" के रूप में प्रस्तुत किया गया है ( uint32_t) के पक्ष में बनाम निर्देश गिनती / गति (के पक्ष में uint_fast32_t) - यहां तक ​​कि यह मेरे लिए स्पष्ट नहीं है। हां, कुछ प्लेटफार्मों पर आपको कुछ 32-बिट संचालन के लिए अतिरिक्त निर्देशों की आवश्यकता होगी , लेकिन आप कुछ निर्देशों को भी सहेजेंगे क्योंकि:

  • एक छोटे प्रकार का उपयोग करने से अक्सर कंपाइलर दो 32-बिट को पूरा करने के लिए एक 64-बिट ऑपरेशन का उपयोग करके आसन्न संचालन को चतुराई से संयोजित करने की अनुमति देता है। इस प्रकार के "गरीब आदमी के वैश्वीकरण" का एक उदाहरण असामान्य नहीं है। उदाहरण के लिए, एक निरंतर की बनाने struct two32{ uint32_t a, b; }में raxकी तरह two32{1, 2} अनुकूलित किया जा सकता है एक भी में mov rax, 0x2000164-बिट संस्करण दो निर्देश की जरूरत है, जबकि। सिद्धांत रूप में यह आसन्न अंकगणितीय संचालन (एक ही ऑपरेशन, विभिन्न ऑपरेंड) के लिए भी संभव होना चाहिए, लेकिन मैंने इसे अभ्यास में नहीं देखा है।
  • कम "मेमोरी उपयोग" भी अक्सर कम निर्देशों की ओर जाता है, भले ही मेमोरी या कैश फ़ुटप्रिंट कोई समस्या न हो, क्योंकि इस प्रकार की किसी भी संरचना या सरणियों की प्रतिलिपि बनाई जाती है, तो आपको प्रति रजिस्टर प्रति हिरन के लिए दो बार धमाकेदार कॉपी मिलती है।
  • छोटे डेटा प्रकार अक्सर SysV ABI जैसे बेहतर आधुनिक कॉलिंग सम्मेलनों का फायदा उठाते हैं जो डेटा संरचना डेटा को कुशलतापूर्वक रजिस्टरों में पैक करते हैं। उदाहरण के लिए, आप रजिस्टरों में 16-बाइट संरचना में वापस आ सकते हैं rdx:rax। 4 uint32_tमानों (एक स्थिर से आरंभिक) के साथ संरचना लौटने वाले फ़ंक्शन के लिए , जो अनुवाद करता है

    ret_constant32():
        movabs  rax, 8589934593
        movabs  rdx, 17179869187
        ret
    

    4 64-बिट के साथ समान संरचना को एक ही काम uint_fast32_tकरने के लिए एक रजिस्टर चाल और मेमोरी के लिए चार स्टोर की आवश्यकता होती है (और कॉल करने वाला शायद वापसी के बाद मेमोरी से मानों को पढ़ने के लिए व्यवहार करेगा):

    ret_constant64():
        mov     rax, rdi
        mov     QWORD PTR [rdi], 1
        mov     QWORD PTR [rdi+8], 2
        mov     QWORD PTR [rdi+16], 3
        mov     QWORD PTR [rdi+24], 4
        ret
    

    इसी प्रकार, जब संरचना संबंधी तर्क पारित होते हैं, तो 32-बिट मान पैरामीटर के लिए उपलब्ध रजिस्टरों में दो बार के बारे में पैक किए जाते हैं, इसलिए यह कम संभावना बनाता है कि आप रजिस्टर तर्कों से बाहर निकल जाएंगे और स्टैक 1 को फैलाना होगा ।

  • यहां तक ​​कि अगर आप uint_fast32_tउन स्थानों के लिए उपयोग करना चुनते हैं जहां "गति मायने रखती है" तो आपके पास अक्सर ऐसे स्थान भी होंगे जहां आपको निश्चित आकार के प्रकार की आवश्यकता होती है। उदाहरण के लिए, बाहरी इनपुट के लिए मानों को पार करते समय, बाहरी इनपुट से, आपके एबीआई के हिस्से के रूप में, एक संरचना के हिस्से के रूप में, जिसे विशिष्ट लेआउट की आवश्यकता होती है, या क्योंकि आप uint32_tस्मृति फ़ुटप्रिंट को बचाने के लिए मूल्यों के बड़े एकत्रीकरण के लिए चालाकी से उपयोग करते हैं। उन स्थानों पर जहां आपके uint_fast32_tऔर `` uint32_t` प्रकारों को इंटरफ़ेस करने की आवश्यकता है, आपको (विकास जटिलता के अतिरिक्त), अनावश्यक साइन एक्सटेंशन या अन्य आकार-बेमेल संबंधित कोड मिल सकते हैं। कंपाइलर कई मामलों में इसे दूर करने के लिए एक ठीक काम करते हैं, लेकिन विभिन्न आकारों के प्रकारों को मिलाते समय इसे अनुकूलित आउटपुट में देखना असामान्य नहीं है।

आप ऊपर दिए गए कुछ उदाहरणों और गॉडबोल्ट पर और अधिक के साथ खेल सकते हैं ।


1 स्पष्ट होने के लिए, रजिस्टरों में कसकर पैकिंग संरचनाओं का सम्मेलन हमेशा छोटे मूल्यों के लिए एक स्पष्ट जीत नहीं है। इसका मतलब यह है कि छोटे मूल्यों का उपयोग करने से पहले उन्हें "निकाला" जा सकता है। उदाहरण के लिए एक साधारण फ़ंक्शन जो दो संरचना सदस्यों के योग को एक साथ लौटाता है mov rax, rdi; shr rax, 32; add edi, eax, 64-बिट संस्करण के लिए थोड़ी देर के लिए प्रत्येक तर्क को अपना रजिस्टर मिलता है और बस एक addया एक की आवश्यकता होती है lea। फिर भी यदि आप स्वीकार करते हैं कि "कसकर पैक संरचनाओं को पास करते समय" डिजाइन समग्र रूप से समझ में आता है, तो छोटे मूल्य इस सुविधा का अधिक लाभ उठाएंगे।


x86-64 लिनक्स पर glibc 64-बिट का उपयोग करता है uint_fast32_t, जो एक IMO की गलती है। (जाहिरा तौर uint_fast32_tपर विंडोज़ विंडोज़ पर 32-बिट प्रकार है।) x86-64 लिनक्स पर 64-बिट होने के कारण मैं कभी भी uint_fast32_tयह सलाह नहीं दूंगा कि कोई भी उपयोग करें : यह कम निर्देश गणना के लिए अनुकूलित है (फ़ंक्शन आर्ग और रिटर्न मान को कभी भी शून्य-एक्सटेंशन की आवश्यकता नहीं है एक प्रमुख इंडेक्स के रूप में उपयोग) प्रमुख महत्वपूर्ण प्लेटफार्मों में से एक पर समग्र गति या कोड-आकार के लिए नहीं।
पीटर कॉर्ड्स

2
ओह ठीक है, मैंने SysV ABI के बारे में आपकी टिप्पणी ऊपर पढ़ी है, लेकिन जैसा कि आप बाद में बताते हैं कि शायद यह एक अलग समूह / दस्तावेज था जिसने इसे तय किया - लेकिन मुझे लगता है कि एक बार ऐसा होता है कि यह बहुत ज्यादा पत्थर में सेट होता है। मुझे लगता है कि यह और भी संदेहास्पद है कि शुद्ध चक्र गणना / निर्देश गिनती बड़े प्रकार के भी हैं जो कि अच्छे फुट-बिट ऑपरेशन सपोर्ट के बिना प्लेटफॉर्म पर भी मेमोरी फुटप्रिंट इफेक्ट्स और वेक्टराइजेशन की अनदेखी करते हैं - क्योंकि अभी भी ऐसे मामले हैं जहां कंपाइलर बेहतर छोटे प्रकारों को ऑप्टिमाइज़ कर सकते हैं। मैंने ऊपर कुछ उदाहरण जोड़े। @PeterCordes
BeeOnRope

SysV एक ही रजिस्टर में कई स्ट्रक्चर मेंबर्स को पैक करते समय या जब वापस लौटते हैं तो काफी बार ज्यादा निर्देश देने पड़ते हैं । यदि दोनों सदस्य समय-स्थिरांक को संकलित नहीं करते हैं, तो आमतौर पर केवल एक OR से अधिक होता है, और कॉल करने वाले को रिटर्न मानों को अनपैक करना पड़ता है। ( Bugs.llvm.org/show_bug.cgi?id=34840 LLVM वापसी-मूल्य निजी कार्यों के लिए पारित करने का अनुकूलन, और पूरे लेने के रूप में 32-बिट पूर्णांक व्यवहार करना चाहिए ताकि में अलग है करने के लिए एक 64-बिट निरंतर की आवश्यकता होगी, के बजाय pair<int,bool>pair<int,int>raxbooldltest
इट

1
मुझे लगता है कि संकलक आमतौर पर कार्यों को विभाजित नहीं करते हैं। एक अलग फ़ंक्शन के रूप में एक तेज़-पथ को छीलना एक उपयोगी स्रोत-स्तरीय अनुकूलन है (विशेषकर हेडर में जहां यह इनलाइन हो सकता है)। बहुत अच्छा हो सकता है अगर 90% इनपुट "कुछ भी नहीं करें"; कॉलर के लूप में फ़िल्टरिंग करना एक बड़ी जीत है। IIRC, लिनक्स __attribute__((noinline))यह सुनिश्चित करने के लिए बिल्कुल उपयोग करता है कि gcc त्रुटि से निपटने के कार्य को इनलाइन नहीं करता है और कुछ महत्वपूर्ण कर्नेल फ़ंक्शंस के तेज़ पथ पर push rbx/ .../ pop rbx/ ... का एक गुच्छा डाल देता है जिसमें कई कॉलर होते हैं और स्वयं इनलाइन नहीं करते हैं।
पीटर कॉर्ड्स

1
जावा में यह वास्तव में बहुत महत्वपूर्ण है क्योंकि इनलाइनिंग आगे अनुकूलन के लिए बहुत महत्वपूर्ण है (विशेष रूप से डी-वर्चुअलाइजेशन जो सी ++ के विपरीत व्याप्त है), इसलिए यह अक्सर एक फास्ट-पथ को विभाजित करने के लिए भुगतान करता है, और "बायोटेक ऑप्टिमाइज़ेशन" वास्तव में एक चीज है (हालांकि के बावजूद) पारंपरिक ज्ञान कि यह कोई मतलब नहीं है क्योंकि जेआईटी अंतिम संकलन करता है) बस बायोटेक को नीचे लाने के लिए क्योंकि टोलिंग निर्णय बायटेकोड के आकार पर आधारित होते हैं, इनबिल्ड मशीन कोड आकार में नहीं (और सहसंबंध परिमाण के आदेश से भिन्न हो सकते हैं)।
BeeOnRope

4

व्यावहारिक उद्देश्यों के लिए, uint_fast32_tपूरी तरह से बेकार है। यह सबसे व्यापक मंच (x86_64) पर गलत तरीके से परिभाषित किया गया है, और वास्तव में कहीं भी कोई भी लाभ प्रदान नहीं करता है जब तक कि आपके पास बहुत कम गुणवत्ता वाला कंपाइलर न हो। वैचारिक रूप से, डेटा संरचनाओं / सरणियों में "तेज" प्रकारों का उपयोग करना कभी भी समझ में नहीं आता है - जिस प्रकार से आपको संचालन करने के लिए अधिक कुशल होने से मिलने वाली किसी भी बचत को आकार में वृद्धि की लागत (कैश मिसेज इत्यादि) से बौना हो जाएगा। आपका कार्य डेटा सेट। और व्यक्तिगत स्थानीय चर (लूप काउंटर, टेम्प्स, आदि) के लिए एक गैर-खिलौना संकलक आमतौर पर उत्पन्न कोड में एक बड़े प्रकार के साथ काम कर सकता है यदि यह अधिक कुशल है, और केवल शुद्धता के लिए नाममात्र आकार में छोटा (और साथ में) हस्ताक्षरित प्रकार, यह आवश्यक नहीं है)।

एक संस्करण जो सैद्धांतिक रूप से उपयोगी है uint_least32_t, जब आपको किसी भी 32-बिट मान को संग्रहीत करने में सक्षम होने की आवश्यकता होती है, लेकिन उन मशीनों के लिए पोर्टेबल होना चाहते हैं जिनमें सटीक-आकार 32-बिट प्रकार की कमी होती है। व्यावहारिक रूप से, बोलना, हालांकि, ऐसा कुछ नहीं है जिसके बारे में आपको चिंता करने की आवश्यकता है।


4

मेरी समझ में, intशुरू में अतिरिक्त गारंटी के साथ "देशी" पूर्णांक प्रकार माना जाता था कि यह कम से कम 16 बिट आकार का होना चाहिए - ऐसा कुछ जिसे "उचित" आकार वापस माना जाता था।

जब 32-बिट प्लेटफ़ॉर्म अधिक सामान्य हो गए, तो हम कह सकते हैं कि "उचित" आकार 32 बिट्स में बदल गया है:

  • आधुनिक विंडोज intसभी प्लेटफार्मों पर 32-बिट का उपयोग करता है।
  • POSIX गारंटी देता है कि intकम से कम 32 बिट्स है।
  • सी #, जावा में टाइप intहोता है जो बिल्कुल 32 बिट्स होने की गारंटी है।

लेकिन जब 64-बिट प्लेटफ़ॉर्म आदर्श बन गया, तो किसी ने intभी 64-बिट पूर्णांक बनने का विस्तार नहीं किया क्योंकि:

  • पोर्टेबिलिटी: बहुत सारे कोड intआकार में 32 बिट होने पर निर्भर करते हैं ।
  • मेमोरी की खपत: प्रत्येक के लिए दोहरीकरण मेमोरी का उपयोग intअधिकांश मामलों के लिए अनुचित हो सकता है, क्योंकि अधिकांश मामलों में उपयोग की संख्या 2 बिलियन से बहुत कम है।

अब, तुम क्यों पसंद करेंगे uint32_tकरने के लिए uint_fast32_t? समान कारणों से भाषाओं के लिए, C # और Java हमेशा निश्चित आकार के पूर्णांक का उपयोग करते हैं: प्रोग्रामर विभिन्न प्रकारों के संभावित आकारों के बारे में सोचकर कोड नहीं लिखता है, वे उस मंच पर एक मंच और परीक्षण कोड के लिए लिखते हैं। ज्यादातर कोड स्पष्ट रूप से डेटा प्रकारों के विशिष्ट आकारों पर निर्भर करता है। और यही कारण है कि uint32_tज्यादातर मामलों के लिए एक बेहतर विकल्प है - यह अपने व्यवहार के बारे में किसी भी अस्पष्टता की अनुमति नहीं देता है।

इसके अलावा, uint_fast32_t32 बिट्स के बराबर या अधिक आकार वाले प्लेटफॉर्म पर वास्तव में सबसे तेज़ प्रकार है? ज़रुरी नहीं। Windows पर x86_64 के लिए GCC द्वारा इस कोड संकलक पर विचार करें:

extern uint64_t get(void);

uint64_t sum(uint64_t value)
{
    return value + get();
}

उत्पन्न विधानसभा इस तरह दिखता है:

push   %rbx
sub    $0x20,%rsp
mov    %rcx,%rbx
callq  d <sum+0xd>
add    %rbx,%rax
add    $0x20,%rsp
pop    %rbx
retq

अब अगर आप को बदलने get()के लिए की वापसी मान uint_fast32_t(जो विंडोज x86_64 पर 4 बाइट है) आप इस मिल:

push   %rbx
sub    $0x20,%rsp
mov    %rcx,%rbx
callq  d <sum+0xd>
mov    %eax,%eax        ; <-- additional instruction
add    %rbx,%rax
add    $0x20,%rsp
pop    %rbx
retq

ध्यान दें कि mov %eax,%eaxफ़ंक्शन कॉल के बाद अतिरिक्त निर्देश को छोड़कर कैसे उत्पन्न कोड लगभग समान है जो कि 32-बिट मान को 64-बिट मान में विस्तारित करने के लिए है।

ऐसा कोई मुद्दा नहीं है यदि आप केवल 32-बिट मानों का उपयोग करते हैं, लेकिन आप शायद उन size_tचर (सरणी आकार शायद?) का उपयोग कर रहे हैं और उन x86_64 पर 64 बिट्स हैं। लिनक्स uint_fast32_tपर 8 बाइट्स हैं, इसलिए स्थिति अलग है।

कई प्रोग्रामर का उपयोग intतब किया जाता है जब उन्हें छोटे मूल्य को वापस करने की आवश्यकता होती है (चलो [-32,32] सीमा में कहते हैं)। यह पूरी तरह से काम करेगा यदि intप्लेटफ़ॉर्म देशी पूर्णांक आकार का होगा, लेकिन चूंकि यह 64-बिट प्लेटफ़ॉर्म पर नहीं है, इसलिए एक अन्य प्रकार जो प्लेटफ़ॉर्म देशी प्रकार से मेल खाता है, वह एक बेहतर विकल्प है (जब तक कि यह छोटे आकार के अन्य पूर्णांक के साथ अक्सर उपयोग नहीं किया जाता है)।

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


एक अन्य संकेत जो दिखाता है कि intमूल पूर्णांक प्रकार "पूर्णांक पदोन्नति नियम" था। अधिकांश सीपीयू केवल देशी पर परिचालन कर सकते हैं, इसलिए 32 बिट सीपीयू आमतौर पर केवल 32-बिट परिवर्धन, घटाव आदि कर सकते हैं (इंटेल सीपीयू यहां अपवाद हैं)। पूर्ण आकार और स्टोर निर्देशों के माध्यम से अन्य प्रकार के पूर्ण आकार का समर्थन किया जाता है। उदाहरण के लिए, 8-बिट मान को उपयुक्त "लोड 8-बिट हस्ताक्षरित" या "लोड 8-बिट अहस्ताक्षरित" निर्देश के साथ लोड किया जाना चाहिए और लोड के बाद 32 बिट तक मूल्य का विस्तार होगा। पूर्णांक पदोन्नति नियम के बिना C कंपाइलरों को उन प्रकारों के लिए थोड़ा अधिक कोड जोड़ना होगा जो मूल प्रकार की तुलना में छोटे प्रकार का उपयोग करते हैं। दुर्भाग्य से, यह 64-बिट आर्किटेक्चर के साथ अब और पकड़ नहीं रखता है क्योंकि कंपाइलर्स को अब कुछ मामलों में अतिरिक्त निर्देशों का उत्सर्जन करना होगा (जैसा कि ऊपर दिखाया गया था)।


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

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

मैं दृढ़ता से uint_fast32_tअस्पष्ट, सभी लेकिन बहुत ही चुनिंदा परिस्थितियों में उपयोगिता के बारे में सहमत हूं । मुझे संदेह है कि uint_fastN_tसभी के लिए ड्राइविंग कारण "समायोजित करने के लिए है" चलो unsigned64-बिट के रूप में उपयोग नहीं करते हैं , भले ही यह अक्सर नए प्लेटफॉर्म पर सबसे तेज़ होता है, क्योंकि बहुत अधिक कोड टूट जाएगा "लेकिन" मुझे अभी भी कम से कम एन-बिट प्रकार चाहिए " अगर मैं कर सकता तो मैं आपको फिर से यूवी देता।
chux -

अधिकांश 64-बिट आर्किटेक्चर 32-बिट पूर्णांक पर आसानी से काम कर सकते हैं। यहां तक ​​कि डीईसी अल्फा (जो कि मौजूदा 32-बिट आईएसए जैसे पावरपीसी 64 या एमआईपीएस 64 के विस्तार के बजाय एक शाखा-नई 64-बिट वास्तुकला थी) में 32 और 64-बिट लोड / स्टोर थे। (लेकिन बाइट या 16-बिट लोड / स्टोर नहीं!)। अधिकांश निर्देश केवल 64-बिट थे, लेकिन इसमें 32-बिट ऐड / उप के लिए मूल एचडब्ल्यू का समर्थन था और परिणाम में 32 बिट्स को छोटा किया गया था। ( alasir.com/articles/alpha_history/press/alpha_intro.html ) इसलिए int64 बिट बनाने से लगभग कोई गति प्राप्त नहीं होगी , और आमतौर पर कैश फ़ुटप्रिंट से गति हानि होती है।
पीटर कॉर्ड्स

इसके अलावा, यदि आपने int64-बिट बनाया है, तो आपके uint32_tनिश्चित-चौड़ाई वाले टाइपफेड को एक __attribute__या अन्य हैक, या कुछ कस्टम प्रकार की आवश्यकता होगी जो इससे छोटा है int। (या short, लेकिन फिर आपके लिए वही समस्या है uint16_t।) कोई भी ऐसा नहीं चाहता है। 32-बिट लगभग सब कुछ के लिए पर्याप्त है (16-बिट के विपरीत); 32-बिट पूर्णांक का उपयोग करते समय जब आपको आवश्यकता होती है तो 64-बिट मशीन पर किसी भी सार्थक तरीके से "अक्षम" नहीं होता है।
पीटर कॉर्डेस

2

कई मामलों में, जब एल्गोरिथ्म डेटा की एक सरणी पर काम करता है, तो प्रदर्शन में सुधार करने का सबसे अच्छा तरीका कैश मिस की संख्या को कम करना है। प्रत्येक तत्व जितना छोटा होगा, उनमें से अधिक कैश में फिट हो सकते हैं। यही कारण है कि 64-बिट मशीनों पर 32-बिट पॉइंटर्स का उपयोग करने के लिए बहुत सारे कोड अभी भी लिखे गए हैं: उन्हें डेटा के 4 GiB के करीब कुछ भी नहीं चाहिए, लेकिन सभी पॉइंटर्स और ऑफ़सेट्स बनाने की लागत को चार के बजाय आठ बाइट्स की आवश्यकता होती है पर्याप्त होगा।

कुछ ABI और प्रोटोकॉल भी हैं जिन्हें बिल्कुल 32 बिट्स की आवश्यकता होती है, उदाहरण के लिए, IPv4 पते। इसका uint32_tवास्तव में मतलब है: बिल्कुल 32 बिट्स का उपयोग करना , भले ही सीपीयू में कुशल हो या नहीं। इन्हें longया के रूप में घोषित किया जाता था unsigned long, जिससे 64-बिट संक्रमण के दौरान बहुत सारी समस्याएं होती थीं। यदि आपको केवल एक अहस्ताक्षरित प्रकार की आवश्यकता है जो कम से कम 2 1-1 तक की संख्या रखता है, तो यह परिभाषा है unsigned longक्योंकि पहले सी मानक निकला था। व्यवहार में, हालांकि, पर्याप्त पुराने कोड ने यह मान लिया था कि कोई longभी सूचक या फ़ाइल ऑफसेट या टाइमस्टैम्प पकड़ सकता है, और पर्याप्त पुराने कोड ने माना कि यह बिल्कुल 32 बिट्स चौड़ा था, इसलिए कंपाइलर आवश्यक longरूप से int_fast32_tबहुत अधिक सामान को तोड़ने के बिना नहीं बना सकते ।

सिद्धांत रूप में, यह उपयोग करने के लिए एक कार्यक्रम के लिए अधिक भविष्य-प्रमाण होगा uint_least32_t, और शायद गणना के लिए uint_least32_tएक uint_fast32_tचर में तत्वों को लोड भी करता है। ऐसा कार्यान्वयन जिसके पास कोई uint32_tप्रकार नहीं था , मानक के साथ औपचारिक अनुपालन में भी खुद को घोषित कर सकता है! (यह सिर्फ कई मौजूदा कार्यक्रमों को संकलित करने में सक्षम नहीं होगा।) व्यवहार में, वहाँ कोई आर्किटेक्चर नहीं है int, जहां uint32_t, और uint_least32_tसमान नहीं हैं, और कोई लाभ नहीं है, वर्तमान में , के प्रदर्शन के लिए uint_fast32_t। तो क्यों चीजों को ओवरकॉम्पलेट करते हैं?

फिर भी उस कारण 32_tको longदेखें, जब हमारे पास पहले से मौजूद सभी प्रकार के अस्तित्व के लिए आवश्यक थे , और आप देखेंगे कि उन धारणाओं को हमारे चेहरे पर पहले भी उड़ा दिया गया था। आपका कोड अच्छी तरह से किसी दिन मशीन पर चल सकता है, जहां सटीक-चौड़ाई 32-बिट गणना मूल शब्द के आकार की तुलना में धीमी है, और आप uint_least32_tभंडारण के लिए और uint_fast32_tधार्मिक रूप से गणना के लिए उपयोग करना बेहतर होगा । या अगर आप उस पुल को पार कर लेंगे जब आप इसे प्राप्त करेंगे और बस कुछ सरल चाहते हैं, तो unsigned long


लेकिन ऐसे आर्किटेक्चर हैं जहां int32 बिट्स नहीं हैं, उदाहरण के लिए ILP64। ऐसा नहीं है कि वे आम हैं।
अंती हापला

मुझे नहीं लगता कि ILP64 वर्तमान काल में मौजूद है? कई वेबपेजों का दावा है कि "क्रे" इसका उपयोग करता है, जिनमें से सभी 1997 से एक ही यूनिक्स डॉट ओआरजी का हवाला देते हैं, लेकिन '90 के दशक के मध्य में UNICOS ने वास्तव में कुछ अजीब किया और आज के क्रेज़ इंटेल हार्डवेयर का उपयोग करते हैं। उसी पृष्ठ का दावा है कि ईटीए सुपर कंप्यूटर ने ILP64 का उपयोग किया था, लेकिन वे बहुत समय पहले व्यवसाय से बाहर हो गए। विकिपीडिया का दावा है कि सोलारिस से लेकर SPARC64 तक HAL का पोर्ट ILP64 का उपयोग करता है, लेकिन वे भी वर्षों से व्यवसाय से बाहर हैं। CppReference कहता है कि ILP64 का उपयोग केवल कुछ शुरुआती 64-बिट यूनियनों में किया गया था। तो यह केवल कुछ बहुत गूढ़ रेट्रोकोम्प्यूटिंग के लिए प्रासंगिक है।
डेविस्लोर

ध्यान दें कि यदि आप आज इंटेल की मैथ कर्नेल लाइब्रेरी के "ILP64 इंटरफ़ेस" का उपयोग करते हैं, intतो 32 बिट्स चौड़ा होगा। प्रकार MKL_INTहै जो बदल जाएगा।
डेविस्लोर

1

एक सीधा जवाब देने के लिए: मुझे लगता है कि असली कारण uint32_tका उपयोग क्यों किया जाता है uint_fast32_tया uint_least32_tबस इतना है कि यह टाइप करना आसान है, और छोटा होने के कारण पढ़ने के लिए बहुत अच्छा है: यदि आप कुछ प्रकारों के साथ संरचना बनाते हैं, और उनमें से कुछ हैं uint_fast32_tया इसी तरह की है, तो यह अक्सर मुश्किल के साथ अच्छी तरह उन्हें संरेखित करने के लिए है intया boolया अन्य (: बिंदु में मामले जो काफी कम हैं सी में प्रकार, charबनाम character)। मैं निश्चित रूप से कठिन डेटा के साथ इसे वापस नहीं कर सकता, लेकिन अन्य उत्तर केवल कारण पर भी अनुमान लगा सकते हैं।

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

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

यही कारण है कि, मुझे लगता है, प्रोग्रामर आलस्य के कारण छोटा प्रकार ज्यादातर मामलों में जीत जाता है।

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