मेरी समझ में, 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_t
32 बिट्स के बराबर या अधिक आकार वाले प्लेटफॉर्म पर वास्तव में सबसे तेज़ प्रकार है? ज़रुरी नहीं। Windows पर x86_64 के लिए GCC द्वारा इस कोड संकलक पर विचार करें:
extern uint64_t get(void);
uint64_t sum(uint64_t value)
{
return value + get();
}
उत्पन्न विधानसभा इस तरह दिखता है:
push
sub $0x20,
mov
callq d <sum+0xd>
add
add $0x20,
pop
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-बिट आर्किटेक्चर के साथ अब और पकड़ नहीं रखता है क्योंकि कंपाइलर्स को अब कुछ मामलों में अतिरिक्त निर्देशों का उत्सर्जन करना होगा (जैसा कि ऊपर दिखाया गया था)।