2010-05-04 93 views
7

मैं दो सी ++ फ़ाइलें, file1.cpp और के रूप मेंसमारोह घोषणा और सी ++

//file1.cpp 
#include<cstdio> 
void fun(int i) 
{ 
    printf("%d\n",i); 
} 

//file2.cpp 
void fun(double); 
int main() 
{ 
    fun(5); 
} 

file2.cpp कहना जब मैं उन्हें संकलन और ++ फ़ाइलों उन्हें ग के रूप में लिंक, मैं कोई त्रुटि मिलती है "अपरिभाषित के संदर्भ में मज़ा (डबल) "।
लेकिन जब मैं इसे सी फाइलों के रूप में करता हूं, मुझे त्रुटि नहीं मिलती है और 0 की बजाय 0 मुद्रित किया जाता है।
कृपया कारण बताएं।
इसके अलावा मैं यह पूछना चाहता हूं कि हमें इसे परिभाषित करने से पहले एक फ़ंक्शन घोषित करने की आवश्यकता है क्योंकि
मैंने इसे फ़ाइल 1.cpp में घोषित नहीं किया है लेकिन संकलन में कोई त्रुटि नहीं आती है।

+2

ऑफ विषय: यदि अपने पिछले किसी भी प्रश्न का अपनी संतुष्टि के लिए उत्तर दिया गया, तो आप वापस जाकर स्वीकार करना चाहिए कहा जवाब। बस अच्छा होने के लिए। – outis

+0

बस @outis में जोड़ने के लिए: ऐसा करने से संभावना है कि किसी को अपने सवालों के जवाब में वृद्धि होगी। – ereOn

उत्तर

6

इस समारोह से अधिक भार की वजह से सबसे अधिक संभावना है। सी के साथ संकलन करते समय, fun(double) पर कॉल का असेंबली फ़ंक्शन _fun पर कॉल में अनुवाद किया जाता है, जिसे बाद के चरण में जोड़ा जाएगा। वास्तविक परिभाषा में असेंबली का नाम _fun है, भले ही यह डबल की बजाय int लेता है, और fun(double) कहलाता है तो लिंकर इसका उपयोग करेगा।

सी ++ दूसरी ओर, विधानसभा नाम mangles ताकि आप काम करने के लिए अधिक भार के लिए क्रम में fun(double) के लिए fun(int) और [email protected] के लिए [email protected] की तरह कुछ मिलेगा। लिंकर देखेंगे कि इनके अलग-अलग नाम हैं और एक त्रुटि उत्पन्न हुई है कि इसे fun(double) की परिभाषा नहीं मिल सकती है।

अपने दूसरे प्रश्न के लिए आम तौर पर एक शीर्षलेख में किए गए फ़ंक्शन प्रोटोटाइप घोषित करना एक अच्छा विचार है, खासकर यदि फ़ंक्शन एकाधिक फ़ाइलों में उपयोग किया जाता है। आपके कंपाइलर में प्रोटोटाइप गायब होने के लिए एक चेतावनी विकल्प होना चाहिए, जीसीसी -Wmissing-prototypes का उपयोग करता है।

// file1.hpp 
#ifndef FILE1_HPP 
#define FILE1_HPP 
void fun(int) 
#endif 

// file1.c 
#include "file1.hpp" 
... 

// file2.c 
#include "file1.hpp" 
int main() 
{ 
    fun(5); 
} 

सेट अप होने पर आपका कोड बेहतर होगा यदि आपके प्रोग्राम में कई विरोधाभासी प्रोटोटाइप नहीं होंगे।

+0

लेकिन यह 5 के बजाय 0 क्यों प्रिंट करता है? –

+0

@ हैप क्योंकि यह 5.0 को पूर्णांक के रूप में प्रतिनिधित्व करने वाली बिट्स की व्याख्या कर रहा है, जिसमें एक अनिर्धारित परिणाम –

+3

आईईईई -754 डबल 5.0 का हेक्स प्रतिनिधित्व 0x4014000000000000 होगा। यदि आपका सिस्टम x86 की तरह थोड़ा-अंतियाल है, तो उस स्टैक के पहले चार बाइट्स को पढ़ना 0 होगा, जिसे तब मुद्रित किया जाएगा। –

-3
#include <stdio.h> 

int Sum(int j, int f) 
{ 
    int k; 
    k = j + f; 
    return k; 
} 
main() 
{ 
    int i=3; 
    int j = 6; 

    int k = sum(i,j); 

    printf("%d",k); 
} 

आउटपुट 9

+6

मैं पूरी तरह से खो गया हूं कि इस सवाल के साथ क्या करना है। – MBennett

+1

आपका प्रोग्राम संकलित नहीं करता है, अकेले प्रश्न का उत्तर दें। – avakar

+0

क्या आपके पास उत्तर देने वाले प्रश्न का कोई लिंक है? – Ashish

5

है इसका कारण यह है सी ++ आप कार्यों को ओवरलोड की अनुमति देता है और सी नहीं करता है। यह C++ में इस संबंध के लिए मान्य है:

double fun(int i); 
double fun(double i); 
... 
double fun(int i) { return 1;} 
double fun(double i) { return 2.1; } 

नहीं बल्कि सी

कारण आप अपने सी के साथ यह संकलन करने में सक्षम नहीं हैं में ++ संकलक है, क्योंकि सी ++ संकलक डबल के रूप में देखता है और घोषणा इसके लिए एक परिभाषा खोजने की कोशिश करता है। सी कंपाइलर के साथ, आपको इसके लिए भी एक त्रुटि मिलनी चाहिए, मुझे लगता है कि आपने कोड को ठीक से दर्ज नहीं किया जैसा आपने कहा था कि आपने सी संकलक के साथ परीक्षण करते समय किया था।

मुख्य बिंदु: सी ++ में ओवरलोडिंग कार्य है, सी नहीं करता है।

+0

मैं संकलित और के रूप में सी संकलक के साथ दो फ़ाइलों जुड़ा हुआ जीसीसी -c file1.c जीसीसी -c file2.c जीसीसी -ओ prog file2.o file1.o यह किसी भी त्रुटि नहीं दिखा था और परिणाम 0 के रूप में आया । –

+0

सी कोड वास्तव में मानक के रूप में अमान्य है, हालांकि, व्यवहार में, प्रतीक नामों में केवल फ़ंक्शन का नाम होता है, पूरे हस्ताक्षर नहीं, जिससे लिंकर को त्रुटि अदृश्य हो जाती है। – avakar

+0

जब आप इसे जीसीसी के साथ संकलित करते हैं, तो देखें कि यदि आप इन स्विच को जोड़ते हैं तो क्या होता है -Wall -Werror –

1

सी ++ (एक दुःखद जानवर, आप सहमत होंगे) कार्यों के नामों को उलझाना पसंद करते हैं। इस प्रकार, सी भाग के लिए अपने हेडर फाइल में: शीर्ष पर :

#ifdef __cplusplus 
extern "C" {` 
#endif 
तल पर

:

#ifdef __cplusplus 
} 
#endif 

यह नाम के कुछ वध के लिए नहीं राजी होगा। देखो here

या, अपने cpp में आप कह सकते हैं

extern "C" void fun(double); 
1

सी भाषा का एक धारणा यह है कि कार्यों को वास्तव में अनुवाद के भीतर दिखाई देने वाली घोषणा की आवश्यकता के बिना कॉल करने की अनुमति देता है - यह मानता है कि इस तरह के कार्यों के तर्क सभी int हैं।

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

यह है कि वर्षों से (या नहीं) भाषाओं में कैसे विकसित हुआ। आपके कंपाइलर में शायद इस समस्या के लिए चेतावनी है (निहित कार्य घोषणाएं)।

आप अलग अलग परिणाम देखेंगे जब आप सी कार्यों के रूप में कार्य की घोषणा (वे जब सी ++ स्रोत फ़ाइलों के रूप में संकलित रूप में अपने उदाहरण में सी ++ कार्यों घोषित कर रहे हैं)।

सी ++ की आवश्यकता है इससे पहले कि यह प्रयोग किया जाता है समारोह घोषित करने, सी (जब तक आप अपने संकलक समस्या के बारे में चेतावनी देने के लिए) नहीं है।

0

जब सी के रूप में संकलित ++ आप (वे विभिन्न मापदंडों है जब तक) ही नाम के दो कार्यों की अनुमति है।

fun_int(int x); 
fun_double(double x); 

जब सी में संकलित एक विशिष्ट नाम के साथ केवल एक समारोह है: C++ में इतना लिंकर दो भेद कर सकते हैं नाम mangling प्रयोग किया जाता है।
जब आप file1.c संकलित करते हैं तो यह एक फ़ंक्शन उत्पन्न करता है जो स्टैक से पूर्णांक पढ़ता है और प्रिंट करता है।

जब आप file2.c संकलित करते हैं तो यह देखता है कि मजेदार() एक डबल लेता है। इसलिए यह इनपुट पैरामीटर को स्टैक पर डबल पुश करने के लिए परिवर्तित करता है, फिर कोड में मज़ेदार() को कॉल करता है। चूंकि फ़ंक्शन एक अलग संकलन इकाई में है, वास्तविक पता हल नहीं किया गया है, लेकिन केवल जब लिंकर का आह्वान किया जाता है। जब लिंकर को बुलाया जाता है तो यह मजेदार मज़ेदार कॉल को हल करने की आवश्यकता को देखता है और सही पता लगाता है, लेकिन इसमें कॉल को सत्यापित करने के लिए कोई प्रकार की जानकारी नहीं है।

रनटाइम पर 5 अब एक डबल में परिवर्तित हो गया है और ढेर पर धक्का दिया गया है। फिर मज़ा() आक्रमण किया जाता है। मज़ा() ढेर से एक पूर्णांक पढ़ता है और फिर इसे प्रिंट करता है। चूंकि एक डबल में एक पूर्णांक के लिए एक अलग लेआउट होता है जिसे मुद्रित किया जाएगा कार्यान्वयन परिभाषित किया जाएगा और यह निर्भर करता है कि स्मृति में डबल और int दोनों कैसे बिछाए जाते हैं।

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