2015-11-17 6 views
10
  • ctype.h को शामिल किए बिना लिंक करने के लिए #include<ctype.h> के बिना, निम्नलिखित कार्यक्रम आउटपुट 1 और 0.
  • साथ
  • शामिल कर रहा हूँ यह 1 और 1.

मैं टीडीएम उपयोग कर रहा हूँ आउटपुट -जीसीसी 4.9.2 64-बिट। मुझे आश्चर्य है कि isdigit का कार्यान्वयन पहले मामले में है, और क्यों यह लिंक करने में सक्षम है।क्यों, मैं

#include<stdio.h> 
//#include<ctype.h> 
int main() 
{ 
    printf("%d %d\n",isdigit(48),isdigit(48.4)); 
    return 0; 
} 
+0

क्या यह ctype.h redefines मैक्रो के रूप में isdigit हो सकता है? –

+0

@WouterHuysentruit नहीं, मैं कुछ छुपा नहीं रहा हूँ। इसके अलावा, यदि आपने अभी प्रोग्राम की प्रतिलिपि बनाई है और विचारधारा में चिपकाया है तो यह संकलन और जीसीसी 5.1 पर ठीक जुड़ा हुआ लगता है, लेकिन यह दुर्घटनाग्रस्त हो जाता है। – user1537366

उत्तर

6

डिफ़ॉल्ट जीसीसी द्वारा C90 मानक है जो निहित घोषणाओं की अनुमति देता है (जीएनयू एक्सटेंशन (reference) के साथ) का उपयोग करता है। आपके मामले में समस्या यह है कि आपके पास दो अलग-अलग तर्कों के साथ isdigit पर दो कॉल हैं जो फ़ंक्शन की निहित घोषणा करते समय संकलक को भ्रमित कर सकती हैं, और संभवतः यह सुरक्षित पक्ष पर होने के लिए int isdigit(double) का चयन करती है। यह निश्चित रूप से फ़ंक्शन के लिए गलत प्रोटोटाइप है, जिसका अर्थ है कि जब लाइब्रेरी फ़ंक्शन रन-टाइम पर कॉल किया जाता है तो उसे गलत तर्क के साथ बुलाया जाएगा और आपके पास अपरिभाषित व्यवहार होगा।

जब आप <ctype.h> हेडर फाइल शामिल है, वहाँ एक सही प्रोटोटाइप है, और फिर संकलक जानते हैं कि isdigit एक int तर्क लेता है और कॉल के लिए पूर्णांक 48 को double शाब्दिक 48.4 बदल सकते हैं।


कारण है कि यह लिंक कर रहा है के लिए, यह क्योंकि, जबकि इन कार्यों मैक्रो के रूप में लागू किया जा सकता है, कि एक आवश्यकता नहीं है। एक आवश्यकता यह है कि कम से कम C11 मानक (मेरे पास इस समय कोई पुराना संस्करण उपलब्ध नहीं है) में उन कार्यों को वर्तमान लोकेल से अवगत होना चाहिए जो उनके कार्यान्वयन को मैक्रोज़ के रूप में बहुत कठिन बना देगा, और सामान्य पुस्तकालय कार्यों के रूप में बहुत आसान है। और चूंकि मानक पुस्तकालय हमेशा लिंक होता है (जब तक कि आप अन्यथा जीसीसी नहीं बताते) कार्य उपलब्ध होंगे।

2

सभी #include कथनों में से पहले linking के साथ कुछ भी करने की ज़रूरत नहीं है। में # के साथ कुछ भी याद रखें प्रीप्रोसेसर के लिए है, न कि संकलक या लिंकर।

लेकिन कहा कि समारोह को जोड़ा जाना है ना?

चलो अलग-अलग चरणों में कदम उठाएं।

$ gcc -c -Werror --std=c99 st.c 
st.c: In function ‘main’: 
st.c:5:22: error: implicit declaration of function ‘isdigit’ [-Werror=implicit-function-declaration] 
    printf("%d %d\n",isdigit(48),isdigit(48.4)); 
        ^
cc1: all warnings being treated as errors 

ठीक है जैसा कि आप देखते हैं कि जीसीसी के लिंट (स्थिर विश्लेषक) कार्रवाई में हैं!

जो कुछ भी हम इसे अनदेखा करने के लिए आगे बढ़ना होगा ...

$ gcc -c --std=c99 st.c 
st.c: In function ‘main’: 
st.c:5:22: warning: implicit declaration of function ‘isdigit’ [-Wimplicit-function-declaration] 
    printf("%d %d\n",isdigit(48),isdigit(48.4)); 

इस बार केवल एक चेतावनी। अब हमारे पास वर्तमान निर्देशिका में एक ऑब्जेक्ट फ़ाइल है। के निरीक्षण करते हैं ...

$ nm st.o 
       U isdigit 
0000000000000000 T main 
       U printf 

आप देख सकते हैं printf और isdigit दोनों अपरिभाषित रूप में सूचीबद्ध है। तो कोड कहीं से आना है ना?

चलो इसे लिंक करने के लिए आगे बढ़ें ...

$ gcc st.o 
$ nm a.out | grep 'printf\|isdigit' 
       U [email protected]@GLIBC_2.2.5 
       U [email protected]@GLIBC_2.2.5 

अच्छी तरह से आप देख सकते हैं कि स्थिति हल्की सुधार हुई है। isdigit और printf असहाय अकेले नहीं हैं जैसे वे st.o में थे। आप देख सकते हैं कि दोनों कार्य GLIBC_2.2.5 द्वारा प्रदान किए जाते हैं। लेकिन GLIBC कहां है?

खैर के अंतिम निष्पादन में थोड़ा और अधिक जांच करते हैं ...

$ ldd a.out 
     linux-vdso.so.1 => (0x00007ffe58d70000) 
     libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb66f299000) 
     /lib64/ld-linux-x86-64.so.2 (0x000055b26631d000) 

अहा ... है कि वहाँ libc। तो यह पता चला है, हालांकि आपने कोई निर्देश नहीं दिया है, लिंकर डिफ़ॉल्ट रूप से 3 पुस्तकालयों से जुड़ा हुआ है, उनमें से एक libc है जिसमें printf और isdigit दोनों शामिल हैं।

$gcc -dumpspec 
*link: 
%{!r:--build-id} %{!static:--eh-frame-hdr} %{!mandroid|tno-android-ld:%{m16|m32|mx32:;:-m elf_x86_64}     %{m16|m32:-m elf_i386}     %{mx32:-m elf32_x86_64} --hash-style=gnu --as-needed %{shared:-shared} %{!shared:  %{!static:  %{rdynamic:-export-dynamic}  %{m16|m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}}  %{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}  %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}}  %{static:-static}};:%{m16|m32|mx32:;:-m elf_x86_64}     %{m16|m32:-m elf_i386}     %{mx32:-m elf32_x86_64} --hash-style=gnu --as-needed %{shared:-shared} %{!shared:  %{!static:  %{rdynamic:-export-dynamic}  %{m16|m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}}  %{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}  %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}}  %{static:-static}} %{shared: -Bsymbolic}} 

क्या अन्य दो पुस्तकालयों हैं:

आप द्वारा लिंकर के डिफ़ॉल्ट व्यवहार को देख सकते हैं?

खैर याद है जब आप a.out में खोदे गए, दोनों printf और isdigit अभी भी U अज्ञात मतलब यह है कि के रूप में दिखाया गया है। दूसरे शब्दों में, इन प्रतीकों से जुड़े memory पते नहीं थे।

असल में यह जादू है। इन पुस्तकालयों को वास्तव में रनटाइम के दौरान लोड किया गया था, पुराने सिस्टम जैसे लिंक समय के दौरान नहीं।

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

कई सैद्धांतिक कारण हैं, क्यों चीजें करना आलसी पहले से करने से बेहतर है। मुझे लगता है कि यह एक नया विषय है, जिसे हम किसी अन्य समय चर्चा करेंगे।

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