2014-05-29 4 views
16

मुझे जीसीसी अंतर्निहित कार्यों को समझने में परेशानी है, और बहुत उलझन में लग रहा है।कैसे जीसीसी निर्मित अंतर्निहित फ़ंक्शन

  • लाइब्रेरी फ़ंक्शन और अंतर्निर्मित फ़ंक्शन के बीच क्या अंतर है?

  • क्या कोई अंतर्निहित फ़ंक्शन कर सकता है लेकिन लाइब्रेरी फ़ंक्शन नहीं कर सकता है?

  • क्या मैं एक लाइब्रेरी फ़ंक्शन लिख सकता हूं जो अंतर्निहित फ़ंक्शन printf के समान कार्य करता है? मैं इनपुट पैरामीटर के प्रकार (% एफ, फ्लोट या डबल) कैसे बता सकता हूं?

  • जीसीसी अंतर्निहित कार्यों के मशीन निर्देश पुस्तकालय में संग्रहीत नहीं हैं, है ना? वे कहां हैं?

  • लिंकिंग करते समय, आप इन अंतर्निहित फ़ंक्शन कोड कहां नियंत्रित कर सकते हैं?

  • क्यों कभी कभी मैं की तरह त्रुटि संदेशों पर कर सकते हैं "अपरिभाषित संदर्भ __builtin_stdarg_start करने के लिए" जब

    // main.c 
    #include <stdio.h> 
    int main(void) { 
        printf("hello world!\n"); 
        return 0; 
    } 
    

    जोड़ने कर जीसीसी -c main.c, एनएम से पता चलता main.o में कोई प्रतीक printf, (केवल है कि वहाँ मुख्य (टी) और रखता है (यू)), क्यों?

+0

(इसे टी के साथ अंतर्निहित कहा जाता है) –

+1

आप अपना खुद का प्रिंटफ बना सकते हैं। Stdargs.h शीर्षलेख देखें। – Mabus

+2

जीसीसी आपके 'printf() 'से' puts() 'को अनुकूलित करने (सबसे अधिक संभावना) है क्योंकि आप किसी भी आगे तर्क के बिना' printf() 'के लिए एक साधारण स्ट्रिंग पास कर रहे हैं। देखें: http://linux.die.net/man/3/puts – Thomas

उत्तर

18

एक पुस्तकालय समारोह और एक निर्माण में समारोह के बीच क्या अंतर है?

एक अंतर्निहित फ़ंक्शन एक है कि कंपाइलर को सीधे कंपाइलर के अंदर कुछ ज्ञान है। पुस्तकालय में एक लाइब्रेरी फ़ंक्शन बस परिभाषित किया जाता है। एक अंतर्निहित फ़ंक्शन और एक ही नाम का लाइब्रेरी फ़ंक्शन दोनों मौजूद हो सकता है, इसलिए आपके शेष प्रश्नों के लिए, मैं "लाइब्रेरी फ़ंक्शन" के रूप में "लाइब्रेरी फ़ंक्शन" का निर्माण करूंगा जो अंतर्निहित फ़ंक्शन नहीं है।

क्या कोई बिल्ड-इन फ़ंक्शन कर सकता है लेकिन लाइब्रेरी फ़ंक्शन नहीं कर सकता है?

हां। एक अंतर्निहित समारोह चुन सकते हैं, उदाहरण के लिए, अपने तर्कों का मूल्यांकन करने के लिए नहीं:

int main() { 
    int i = 0; 
    __builtin_constant_p (++i); // checks whether ++i is a constant expression 
           // does not evaluate ++i 
    return i; // returns 0 
} 

इसका कारण यह है एक अंतर्निहित समारोह में कुछ और संकलक, कि वास्तव में किसी भी शामिल करने के लिए की जरूरत नहीं है से तब्दील किया जा सकता फंक्शन कॉल

क्या मैं एक लाइब्रेरी फ़ंक्शन लिख सकता हूं जो फ़ंक्शन printf में निर्माण के समान कार्य करता है?

printf का कुछ अंतर्निहित ज्ञान है, लेकिन अधिकांश भाग के लिए, यह पूरी तरह से करने योग्य है। <stdarg.h> का उपयोग कैसे करें देखें।

मैं इनपुट पैरामीटर (% f, float या double) के प्रकार कैसे बता सकता हूं?

आपको कॉलर पर भरोसा करना है कि प्रारूप स्ट्रिंग शेष तर्कों से मेल खाएं; जब आप double की अपेक्षा करते हैं तो आप int पास करने जैसे कुछ का पता नहीं लगा सकते हैं। लेकिन आपको float और double के बीच अंतर को संभालने की आवश्यकता नहीं है, क्योंकि float से printf को पार करना असंभव है: इसे printf से पहले double (प्रारूप स्ट्रिंग के बावजूद) में परिवर्तित कर दिया जाएगा। किसी भी कंपाइलर जादू की किसी भी आवश्यकता से बचने के लिए printf की आवश्यकताओं को ध्यान से बनाया गया है।

जीसीसी बिल्ड-इन फ़ंक्शंस के मशीन निर्देश पुस्तकालय में संग्रहीत नहीं हैं, है ना?

अंतर्निहित कार्यों को कॉल संकलित समय में बदल दिया जाता है, लेकिन यह परिवर्तन केवल उसी नाम के लाइब्रेरी फ़ंक्शन पर कॉल के परिणामस्वरूप हो सकता है।

वे कहाँ हैं?

यदि रूपांतरण संकलन समय पर किया जाता है, तो मशीन निर्देश नहीं हैं। कॉल को अलग-अलग कोड में बदल दिया गया है, और उस कोड को मशीन निर्देशों का उत्पादन करने के लिए संकलित किया जाता है। यदि परिणाम लाइब्रेरी फ़ंक्शन पर कॉल है, तो उस लाइब्रेरी फ़ंक्शन के लिए मशीन निर्देश लाइब्रेरी का हिस्सा हैं।

लिंकिंग करते समय, आप इन बिल्ड-इन फ़ंक्शन कोड कहां नियंत्रित कर सकते हैं?

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

क्यों कभी कभी मैं की तरह त्रुटि संदेशों पर कर सकते हैं "अपरिभाषित संदर्भ __builtin_stdarg_start करने के लिए" जब __builtin उपसर्ग के बावजूद जोड़ने

कोई बिल्ट-इन समारोह __builtin_stdarg_start वहाँ है कर रही है, है, तो यह करने के लिए एक फोन के रूप में व्यवहार किया जाता है एक पुस्तकालय समारोह। और कोई लाइब्रेरी फ़ंक्शन __builtin_stdarg_start नहीं है, इसलिए लिंकर इसे एक त्रुटि के रूप में पहचानता है।

एक अंतर्निहित फ़ंक्शन __builtin_stdarg_start होता था, लेकिन इसे साल पहले हटा दिया गया था, और कोड को पहले स्थान पर कभी भी इसका उपयोग नहीं करना चाहिए था।

gcc -c main.c, एनएम दिखाता है कि main.o में कोई प्रतीक printf नहीं है, (केवल मुख्य (टी) और रखता है (यू)), क्यों?

ऐसा इसलिए है क्योंकि printf एक अंतर्निहित फ़ंक्शन और लाइब्रेरी फ़ंक्शन के रूप में मौजूद है। बिल्ट-इन फ़ंक्शन आमतौर पर लाइब्रेरी फ़ंक्शन को कॉल करता है, लेकिन कभी-कभी आपके उदाहरण सहित बेहतर करना संभव है। इस मामले में, अंतर्निहित फ़ंक्शन printf लाइब्रेरी फ़ंक्शन printf पर कॉल किए बिना सही परिणाम दे सकता है।

6

वहाँ लगभग बनाया-इन के दो प्रकार हैं: लोगों को जो मानक पुस्तकालय कार्यों के अनुरूप (malloc, printf और strcpy सभी डिफ़ॉल्ट रूप से बनाया-इन माना जाता है), और लोगों को जिसमें एक समकक्ष नहीं है मानक पुस्तकालय - __builtin_expect, __builtin_prefetch, आदि के बारे में सोचें

कंपाइलर को इसी तरह के कॉल के स्थान पर अनुकूलित कोड को उत्सर्जित करने में सक्षम करने के लिए पहले प्रकार के अंतर्निर्मित हैं। मानक लाइब्रेरी से प्रत्येक कॉल के आंतरिक अर्थशास्त्र को जानना, संकलक या तो लाइब्रेरी में मौजूद फ़ंक्शन पर कॉल को उत्सर्जित करने का निर्णय ले सकता है, या उसके स्थान पर कोड के कस्टम-जेनरेट किए गए टुकड़े को उत्सर्जित कर सकता है, ताकि मूल अर्थशास्त्र संरक्षित हैं और कोड बेहतर चलाता है।

दूसरे प्रकार के बिल्ट-इन्स (जिन्हें "इंट्रिनिक्स" भी कहा जाता है) चाल और अनुकूलन सक्षम करता है जो लाइब्रेरी में मौजूद कोड के स्थिर टुकड़े के साथ शायद ही प्राप्त हो सकता है। वे सीपीयू (__builtin_prefetch, __builtin_expect) को संकेत देने के लिए अनुवाद कर सकते हैं, या बेहतर संकलन-समय आत्मनिरीक्षण (__builtin_constant_p, __builtin_types_compatible_p) के साथ सी भाषा को बढ़ाने, या कुछ आर्किटेक्चर-विशिष्ट निर्देशों (__builtin_ffs) के लिए एक सरल, प्लेटफॉर्म-स्वतंत्र इंटरफ़ेस प्रदान करने के लिए अनुवाद कर सकते हैं, __builtin_popcount)।

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