किसी भी उल्लेखनीय C एक्सटेंशन में पूर्णांक प्रकार शामिल हैं जिनका व्यवहार मशीन शब्द आकार से स्वतंत्र है


12

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

uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;

एक आर्किटेक्चर पर जहां int16 बिट्स (अभी भी कई छोटे माइक्रोकंट्रोलर का सच है) यह कोड अच्छी तरह से परिभाषित व्यवहार का उपयोग करके 1 का मान प्रदान करेगा। मशीनों पर जहां int64 बिट्स है, यह अच्छी तरह से परिभाषित व्यवहार का उपयोग करते हुए, फिर से 4294836225 मान प्रदान करेगा। मशीनों पर जहां int32 बिट्स हैं, यह संभवतः -131071 (मैं नहीं जानता कि अगर यह कार्यान्वयन-परिभाषित या अपरिभाषित व्यवहार होगा) का मान निर्दिष्ट करेगा। भले ही कोड कुछ भी नहीं का उपयोग करता है सिवाय इसके कि नाममात्र "तय-आकार" प्रकार के होने के अलावा, मानक के लिए आवश्यक होगा कि उपयोग में आने वाले दो अलग-अलग प्रकार के संकलक आज दो अलग-अलग परिणाम प्राप्त करेंगे, और कई लोकप्रिय संकलक आज एक तिहाई का उत्पादन करेंगे।

यह विशेष उदाहरण कुछ हद तक वंचित है, इसमें मैं वास्तविक दुनिया कोड में दो 16-बिट मान के उत्पाद को सीधे 64-बिट मान पर असाइन करने की अपेक्षा नहीं करूंगा, लेकिन इसे तीन तरीके पूर्णांक दिखाने के लिए एक संक्षिप्त उदाहरण के रूप में चुना गया था प्रोन्नति माना-निश्चित-आकार के अहस्ताक्षरित प्रकारों के साथ सहभागिता कर सकती है। कुछ वास्तविक दुनिया की स्थितियां हैं, जहां गणित के लिए आवश्यक है कि अहस्ताक्षरित प्रकारों पर गणितीय पूर्णांक अंकगणित के नियमों के अनुसार प्रदर्शन किया जाए, अन्य जहां यह आवश्यक है कि यह मॉड्यूलर अंकगणित के नियमों के अनुसार किया जाए, और कुछ जहां वास्तव में नहीं है ' टी मामला चेकसम जैसी चीजों के लिए बहुत सारे वास्तविक दुनिया कोड uint32_tअंकगणित रैपिंग मॉड 2³² पर निर्भर करते हैं , और इसके विपरीत प्रदर्शन करने में सक्षम होते हैंuint16_t अंकगणित और परिणाम प्राप्त करें, जो न्यूनतम हैं, सटीक मॉड 65536 के रूप में परिभाषित किए गए हैं (जैसा कि अपरिभाषित व्यवहार को ट्रिगर करने के विपरीत है)।

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

  1. एक निर्देशन जोड़कर जो संकलक को कुछ निश्चित "मौलिक" पूर्णांक प्रकारों को कुछ आकारों के लिए बाध्य करने का निर्देश देगा।

  2. एक निर्देशन जोड़कर जो संकलक को विभिन्न संवर्धन परिदृश्यों का मूल्यांकन करने के लिए निर्देश देगा, हालांकि मशीन के प्रकारों के विशेष आकार थे, लक्ष्य वास्तुकला पर प्रकारों के वास्तविक आकार की परवाह किए बिना।

  3. जोड़ने एक, (विशिष्ट विशेषताओं के साथ प्रकार की घोषणा जैसे घोषणा करते हैं कि एक प्रकार, एक आधुनिक-65536 रैपिंग बीजीय अंगूठी के रूप में व्यवहार करना चाहिए अंतर्निहित शब्द आकार की परवाह किए बिना, और परोक्ष अन्य प्रकार के लिए परिवर्तनीय नहीं होना चाहिए के माध्यम अनुमति देकर wrap32एक करने के लिए intएक उपज चाहिए 16 बिट्स से बड़ा है wrap32या नहीं , इसके प्रकार के परिणामस्वरूप int, जबकि एक से wrap32सीधे जोड़ना wrap16अवैध होना चाहिए (क्योंकि न तो दूसरे में परिवर्तित हो सकता है)।

मेरी खुद की प्राथमिकता तीसरा विकल्प होगी, क्योंकि यह बहुत सारे कोड के साथ काम करने के लिए असामान्य शब्द आकारों के साथ मशीनों को भी अनुमति देगा जो चर को "लपेटने" की उम्मीद करता है क्योंकि वे पावर-ऑफ-टू आकार के साथ होंगे; कंपाइलर को उपयुक्त व्यवहार करने के लिए बिट-मास्किंग निर्देश जोड़ना पड़ सकता है, लेकिन यदि कोड को एक प्रकार की आवश्यकता होती है, जो मॉड 65536 को लपेटता है, तो यह बेहतर है कि कंपाइलर मशीनों पर ऐसे मास्किंग उत्पन्न करें, जिसके साथ स्रोत कोड को अव्यवस्थित करने की आवश्यकता हो। या बस मशीनों पर अनुपयोगी द्वारा ऐसा कोड है जहाँ इस तरह की मास्किंग की आवश्यकता होगी। मैं उत्सुक हूं, हालांकि, चाहे कोई भी सामान्य एक्सटेंशन हो जो उपरोक्त किसी भी माध्यम से पोर्टेबल व्यवहार को प्राप्त करेगा, या कुछ ऐसे माध्यमों के बारे में जिनके बारे में मैंने नहीं सोचा है।

यह स्पष्ट करने के लिए कि मैं क्या देख रहा हूं, कुछ चीजें हैं; सबसे एहम:

  1. जबकि ऐसे कई तरीके हैं जिनके द्वारा कोड को लिखा जा सकता है ताकि वांछित शब्दार्थ सुनिश्चित किया जा सके (जैसे मैक्रोज़ को परिभाषित करने के लिए विशेष आकार के अनसाइन्ड ऑपरेंड पर गणित करने के लिए ताकि एक परिणाम मिल सके जो स्पष्ट रूप से या तो लपेटता है या नहीं) या कम से कम अवांछित है। शब्दार्थ (जैसे सशर्त रूप से संकलक wrap32_tहोने के लिए एक प्रकार को परिभाषित करता है uint32_tजहां uint32_tप्रचार नहीं किया जाएगा, और यह आंकड़ा है कि यह कोड के लिए बेहतर है जो wrap32_tमशीनों पर संकलन को विफल करने की आवश्यकता है जहां उस प्रकार को बढ़ावा दिया जाएगा जहां इसे चलाने के लिए और फर्जी व्यवहार का उत्पादन करने के लिए, यदि कोड लिखने का कोई तरीका है जो भविष्य के भाषा एक्सटेंशन के साथ सबसे अनुकूल रूप से खेलेंगे, तो इसका उपयोग करना मेरे अपने दृष्टिकोण को तैयार करने से बेहतर होगा।

  2. मेरे पास कुछ ठोस विचार हैं कि कैसे भाषा को बढ़ाया जा सकता है ताकि कई पूर्णांक-आकार के मुद्दों को हल किया जा सके, जिससे कोड को अलग-अलग शब्द आकारों के साथ मशीनों पर समान शब्दार्थ प्राप्त करने की अनुमति मिलती है, लेकिन इससे पहले कि मैं कोई महत्वपूर्ण समय बिताऊं उन्हें लिखना पसंद करता हूं। यह जानने के लिए कि उस दिशा में क्या प्रयास किए गए हैं।

मैं किसी भी तरह से सी मानकों समिति या उनके द्वारा उत्पादित कार्य को नापसंद करने के रूप में नहीं देखना चाहता हूं; हालाँकि, मुझे उम्मीद है कि कुछ वर्षों के भीतर मशीनों पर कोड का काम सही ढंग से करना आवश्यक हो जाएगा, जहां "प्राकृतिक" पदोन्नति प्रकार 32 बिट्स, साथ ही साथ जहां यह 64 बिट्स होंगे। मुझे लगता है कि भाषा के कुछ मामूली विस्तार के साथ (C99 nnd C14 के बीच कई अन्य परिवर्तनों की तुलना में अधिक मामूली) यह न केवल 64-बिट आर्किटेक्चर का उपयोग करके कुशलता से एक स्वच्छ तरीका प्रदान करना संभव होगा, बल्कि सौदेबाजी में भी बातचीत की सुविधा प्रदान करता है। "असामान्य-शब्द-आकार" मशीनें जो मानक ऐतिहासिक रूप से समर्थन करने के लिए पिछड़े पर झुकती हैं [जैसे कि 12-बिट के साथ मशीनों के लिए संभव है charकि कोड चलाने के लिए एक की उम्मीद हैuint32_tरैप करने के लिए mod 2³²]। भविष्य के विस्तार की दिशा पर निर्भर करते हुए, मैं यह भी उम्मीद करूंगा कि मैक्रोज़ को परिभाषित करना संभव होगा, जो आज लिखे गए कोड को आज के कंपाइलरों पर प्रयोग करने योग्य बनाने की अनुमति देगा, जहां डिफ़ॉल्ट पूर्णांक प्रकार "अपेक्षित" के रूप में व्यवहार करते हैं, लेकिन भविष्य के कंपाइलरों पर भी उपयोग करने योग्य है। प्रकार डिफ़ॉल्ट रूप से अलग व्यवहार करेंगे, लेकिन आवश्यक व्यवहार कहां प्रदान कर सकते हैं।


4
@RobertHarvey क्या आप सुनिश्चित हैं? जैसा कि मैं पूर्णांक पदोन्नति को समझता हूं , अगर इससे intबड़ा है uint16_t, तो गुणन के संचालन को बढ़ावा दिया जाएगा intऔर गुणन को intगुणा के रूप में किया जाएगा , और जिसके परिणामस्वरूप intमूल्य को int64_tआरंभीकरण के लिए परिवर्तित किया जाएगा who_knows

3
@RobertHarvey कैसे? ओपी के कोड में, इसका कोई उल्लेख नहीं है int, फिर भी यह अभी भी अंदर आता है (फिर से सी मानक की मेरी समझ सही है।)

2
@RobertHarvey यकीन है कि यह बुरा लगता है, लेकिन जब तक आप इस तरह से बात नहीं कर सकते, आप "कुछ भी गलत कर रहे होंगे" कहकर कुछ भी योगदान नहीं दे रहे हैं। बहुत सवाल यह है कि पूर्णांक पदोन्नति से कैसे बचें, या इसके प्रभावों के आसपास कैसे पहुंचें!

3
@RobertHarvey: सी मानक समिति के ऐतिहासिक लक्ष्यों में से एक लगभग किसी भी मशीन एक 'सी संकलक "के लिए के लिए यह संभव बनाते हैं, और नियमों को विशिष्ट पर्याप्त है करने के लिए किया गया है कि स्वतंत्र रूप से विकसित सी compilers किसी विशेष लक्ष्य मशीन के लिए होगा ज्यादातर विनिमेय हो। यह इस तथ्य से जटिल था कि लोगों ने मानकों का मसौदा तैयार करने से पहले कई मशीनों के लिए सी कंपाइलर लिखना शुरू कर दिया था, और मानक समिति कंपाइलरों को ऐसा कुछ भी करने से मना नहीं करना चाहती थी जो मौजूदा कोड पर भरोसा कर सकती है । मानक के कुछ बल्कि मूलभूत पहलू ...
सुपरकैट

3
... जैसा कि वे इसलिए नहीं हैं क्योंकि किसी ने नियमों का एक सेट तैयार करने की कोशिश की जो "समझदारी" है, बल्कि इसलिए कि समिति उन सभी चीजों को खत्म करने की कोशिश कर रही थी जो स्वतंत्र रूप से लिखे गए संकलक पहले से मौजूद थे। दुर्भाग्य से, इस दृष्टिकोण ने उन मानकों को जन्म दिया है जो प्रोग्रामर को अनुमति देने के लिए एक साथ बहुत अस्पष्ट हैं, यह निर्दिष्ट करने के लिए कि क्या करने की आवश्यकता है, लेकिन कंपाइलरों को "बस करने के लिए" अनुमति देने के लिए विशिष्ट है।
सुपरकाट

जवाबों:


4

इस तरह कोड के विशिष्ट इरादे के रूप में

uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;

64 बिट में गुणा का प्रदर्शन करना है (चर का आकार परिणाम में संग्रहीत हो जाता है), (प्लेटफ़ॉर्म स्वतंत्र) सही परिणाम प्राप्त करने का सामान्य तरीका 64-बिट गुणा करने के लिए किसी एक ऑपरेंड को डालना है:

uint16_t ffff16 = 0xFFFF;
int64_t i_know = (int64_t)ffff16 * ffff16;

मैंने कभी भी किसी C एक्सटेंशन का सामना नहीं किया है जो इस प्रक्रिया को स्वचालित बनाता है।


1
मेरा प्रश्न यह नहीं था कि एक विशेष अंकगणितीय अभिव्यक्ति के सही मूल्यांकन को कैसे बाध्य किया जाए (इस पर निर्भर करता है कि परिणाम किस तरह का व्यक्ति चाहता है, या तो एक ऑपरेंड डाले uint32_tया फिर किसी मैक्रो को या तो परिभाषित करें #define UMUL1616to16(x,y)((uint16_t)((uint16_t)(x)*(uint16_t)(y)))या #define UMUL1616to16(x,y)((uint16_t)((uint32_t)(x)*(uint16_t)(y)))आकार के आधार पर उपयोग करें int) लेकिन इसके बजाय कि क्या हैं अपने स्वयं के मैक्रो को परिभाषित करने के बजाय इस तरह की चीजों को उपयोगी तरीके से कैसे संभालना है, इसके लिए कोई उभरता हुआ मानक।
सुपरकाट

मुझे यह भी उल्लेख करना चाहिए, कि हैशिंग और चेकसम गणना जैसी चीजों के लिए, उद्देश्य अक्सर एक परिणाम लेना और इसे ऑपरेंड के आकार तक छोटा करना होगा। एक अभिव्यक्ति का विशिष्ट उद्देश्य (ushort1*ushort2) & 65535uसभी ऑपरेंड मानों के लिए mod-65536 अंकगणितीय प्रदर्शन करना होगा। C89 तर्क को पढ़ना, मुझे लगता है कि यह बहुत स्पष्ट है कि जबकि लेखकों ने माना कि इस तरह के कोड कुछ कार्यान्वयन पर विफल हो सकते हैं यदि परिणाम 2147483647 से अधिक हो गया, तो उन्हें उम्मीद है कि ऐसे कार्यान्वयन तेजी से दुर्लभ हो जाएंगे। इस तरह के कोड कभी-कभी आधुनिक जीसीसी पर विफल होते हैं।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.