2012-04-06 25 views
9

मैं सी में अभी शुरुआत कर रहा हूँ, और मैं सी के साथ खेल रहा था मैं इस तरह एक सी कोड लिखा था:यह सी प्रोग्राम बिना त्रुटि के संकलित क्यों करता है?

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

हालांकि मैं \ इस्तेमाल किया जानबूझकर, सी संकलक किसी भी त्रुटि फेंक नहीं है। सी प्रतीक में इस प्रतीक का क्या उपयोग किया जाता है?

संपादित करें:

यहां तक ​​कि इस काम करता है:

"\n"; 
+0

"\ n"; यह किसी भी प्रभाव के बिना एक बयान है। यह संकलक द्वारा पूरी तरह से अनदेखा हो जाता है और एक चेतावनी उत्पन्न करता है। Gcc -Wall ध्वज के साथ संकलन करने का प्रयास करें जो संकलन चेतावनियां सक्षम करता है। – dAm2K

+3

आपका मुख्य प्रश्न कई बार उत्तर दिया गया है। '" \ N "; 'के बारे में भाग के संदर्भ में, एक सी प्रोग्राम बयान की सूची (अधिक या कम) है। एक शाब्दिक मूल्य (जैसे '3', या' "\ n" ', या' "हैम्बर्गर" ') एक पूरी तरह से वैध कथन है, भले ही यह कुछ भी _do_ नहीं करता है। – jpm

उत्तर

0

बैकस्लैश \ सी पूर्वप्रक्रमक द्वारा व्याख्या मिलता है। यह अपने निम्नलिखित चरित्र (आपके मामले पर नया लाइन वर्ण) की रक्षा करता है।

+1

असल में, यह 'सुरक्षा' के विपरीत है; यह सुनिश्चित करता है कि बैकस्लैश और नई लाइन दोनों हटा दी गई हैं। –

0

बैकस्लैश बस अगले चरित्र से बच रहा है। इस मामले में, शायद एक लाइन अंत (सीआर) चरित्र। बिल्कुल उचित

+0

सी में भागने केवल तारों के अंदर सक्षम हैं। –

+0

दरअसल, प्रीप्रोसेसर केवल लाइन एंड कैरेक्टर से बच सकता था। भ्रामक के लिए माफ़ी। ऊपर dAm2k द्वारा उत्तर अधिक सटीक है। – rainecc

+0

@MatteoItalia: अनुवाद का चरण 2 है: "बैकस्लैश वर्ण (\\) के तुरंत बाद एक नया-पंक्ति वर्ण हटा दिया जाता है, भौतिक स्रोत लाइनों को लॉजिकल स्रोत लाइन बनाने के लिए हटा दिया जाता है।" (§5.1.1.2/1.1)। –

11

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

§5.1.1.2 C99 मानक के अनुवाद के चरण देखें:

पूर्वता अनुवाद की वाक्य रचना नियमों का पालन चरणों द्वारा निर्दिष्ट किया जाता के बीच में। 5)

  1. शारीरिक स्रोत फ़ाइल multibyte वर्ण, मैप की जाती हैं एक कार्यान्वयन में ढंग से परिभाषित किया, स्रोत वर्ण सेट ( अंत लाइन संकेतकों के लिए नई लाइन पात्रों को शुरू) यदि आवश्यक हो तो। ट्रिग्राफ अनुक्रमों को इसी एकल-वर्ण आंतरिक प्रतिनिधित्व द्वारा प्रतिस्थापित किया गया है।
  2. बैकस्लैश वर्ण (\) के प्रत्येक उदाहरण के तुरंत बाद एक नई लाइन वर्ण हटा दिया जाता है, भौतिक स्रोत लाइनों को लॉजिकल स्रोत लाइन बनाने के लिए विभाजित किया जाता है। किसी भी भौतिक स्रोत लाइन पर केवल अंतिम बैकस्लैश इस तरह के एक विभाजन के भाग होने के योग्य होगा। एक स्रोत फ़ाइल जो खाली नहीं है, एक नए-पंक्ति वर्ण, में समाप्त हो जाएगी जो किसी भी स्प्लिसिंग होने से पहले बैकस्लैश वर्ण से पहले नहीं होनी चाहिए।
  3. स्रोत फ़ाइल प्रीप्रोकैसिंग टोकन 6) और सफेद-स्पेस वर्णों (टिप्पणियों सहित) के अनुक्रमों में विघटित है। एक स्रोत फ़ाइल आंशिक प्रीप्रोकैसिंग टोकन या आंशिक टिप्पणी में समाप्त नहीं होगी। प्रत्येक टिप्पणी को एक स्पेस कैरेक्टर द्वारा प्रतिस्थापित किया जाता है। नए रेखा के पात्र बनाए रखा है। क्या प्रत्येक nonempty नई लाइन के अलावा सफेद-स्पेस वर्णों के अनुक्रम को बनाए रखा गया है या द्वारा प्रतिस्थापित किया गया है एक स्पेस कैरेक्टर कार्यान्वयन-परिभाषित है।
  4. प्रीप्रोकैसिंग निर्देश निष्पादित किए जाते हैं, मैक्रो इनवॉक्शंस का विस्तार किया जाता है, और _Pragma यूनरी ऑपरेटर अभिव्यक्ति निष्पादित की जाती है। यदि एक वर्ण अनुक्रम से मेल खाता है तो सार्वभौमिक वर्ण नाम के सिंटैक्स को टोकन कंसटेनेशन (6.10.3.3) द्वारा उत्पादित किया जाता है, व्यवहार अपरिभाषित होता है।#include प्रीप्रोकैसिंग निर्देश चरण 2 के माध्यम से चरण 1 से क्रमशः नामित हेडर या स्रोत फ़ाइल को संसाधित करने का कारण बनता है। सभी प्रीप्रोकैसिंग निर्देश हटा दिए जाते हैं।
  5. प्रत्येक स्रोत चरित्र सेट सदस्य और चरित्र स्थिरांक में भागने अनुक्रम और स्ट्रिंग अक्षर को निष्पादन वर्ण सेट के संबंधित सदस्य में परिवर्तित कर दिया गया है; यदि कोई संबंधित सदस्य नहीं है, तो इसे शून्य (विस्तृत) वर्ण के अलावा सदस्य परिभाषित कार्यान्वयन में परिवर्तित कर दिया गया है। 7)
  6. निकट स्ट्रिंग शाब्दिक टोकन को समेकित किया जाता है।
  7. टोकन को अलग करने वाले व्हाइट-स्पेस वर्ण अब महत्वपूर्ण नहीं हैं। प्रत्येक प्रीप्रोकैसिंग टोकन को टोकन में परिवर्तित किया जाता है। परिणामी टोकन वाक्य रचनात्मक रूप से और अर्थात् विश्लेषण और अनुवाद इकाई के रूप में अनुवादित हैं।
  8. सभी बाहरी ऑब्जेक्ट और फ़ंक्शन संदर्भ हल किए गए हैं। लाइब्रेरी घटक वर्तमान अनुवाद में परिभाषित कार्यों और ऑब्जेक्ट्स के बाहरी संदर्भों को पूरा करने के लिए लिंक किए गए हैं। ऐसे सभी अनुवादक आउटपुट को प्रोग्राम छवि में एकत्र किया जाता है जिसमें निष्पादन वातावरण में निष्पादन के लिए आवश्यक जानकारी होती है।

5) क्रियान्वयन, अगर इन अलग चरणों पाए जाते हैं के रूप में व्यवहार करेगा, भले ही कई आम तौर पर व्यवहार में एक साथ जोड़ रहे हैं।

6) 6,4 में वर्णित है, preprocessing टोकन में एक स्रोत फ़ाइल के पात्रों को विभाजित करने की प्रक्रिया संदर्भ पर निर्भर है। उदाहरण के लिए, को #include प्रीप्रोकैसिंग निर्देश के भीतर संभालना देखें।

7) एक कार्यान्वयन को सभी गैर-संबंधित स्रोत वर्णों को उसी निष्पादन वर्ण में परिवर्तित करने की आवश्यकता नहीं है।

यदि आप एक खाली करने या अपने आवारा बैकस्लैश के बाद किसी अन्य चरित्र था, तो आप एक संकलन त्रुटि होगा। हम बता सकते हैं कि आपके पास इसके बाद कुछ भी नहीं है क्योंकि आपके पास संकलन त्रुटि नहीं है।


अपने प्रश्न के अन्य भाग, के बारे में:

"\n"; 

काफी अलग है। यह एक साधारण अभिव्यक्ति है जिसका कोई दुष्प्रभाव नहीं है और इसलिए कार्यक्रम पर कोई प्रभाव नहीं पड़ता है। अनुकूलक इसे पूरी तरह से त्याग देगा। जब आप लिखें:

i = 1; 

आपको लगता है कि त्याग दिया जाता है एक मूल्य के साथ एक अभिव्यक्ति है, इसका मूल्यांकन i को संशोधित करने के दुष्प्रभाव के लिए किया जाता है।

कभी कभी, आप की तरह कोड मिल जाएगा:

*ptr++; 

संकलक आपको लगता है कि अभिव्यक्ति का परिणाम त्याग दिया जाता है चेतावनी देगा; अभिव्यक्ति को सरल बनाया जा सकता है:

ptr++; 

और कार्यक्रम में एक ही प्रभाव प्राप्त करेगा।

+0

चरण एक में, "रेखा अंत संकेतक" कार्यान्वयन परिभाषित हैं। सफेद स्थान से पीछे चल लाइन अंत सूचक का हिस्सा माना जा सकता है, इसलिए चरण 2 में, बैकस्लैश तुरंत एक एक नई लाइन पालन किया जाएगा, भले ही मूल इनपुट में सफेद स्थान नहीं था। –

+0

@ जेरीकॉफिन: सिद्धांत रूप में, आप सही हैं। व्यावहारिक रूप से, मेरा सरलीकृत बयान उन सभी आधुनिक वातावरण पर लागू होता है जिन्हें मैंने कभी सुना है। क्या आपके पास एक स्पष्ट काउंटर-उदाहरण है जहां सी कंपाइलर बैकस्लैश-न्यूलाइन स्प्लिसिंग करने से पहले रिक्त स्थान पीछे स्ट्रिप्स करता है? (C99 मानक से सटीक नियम उद्धृत कर रहे हैं, किसी भी टिप्पणी मैं मानक और कार्यान्वयन में कीड़े इस्तेमाल किया जा रहा करने के लिए दूसरे स्थान पर ले आता है।) –

+0

नहीं, एक मौजूदा एक, हालांकि मैं कुछ प्राचीन एक है कि यह किया याद करने लगते हैं समय का हिस्सा –

0

बैकस्लैश प्लस इसके बाद क्या है escape sequence; "\ n" एक साथ न्यूलाइन कैरेक्टर है (एक न्यूलाइन प्रिंट करता है)। एक और महत्वपूर्ण टैब टैब के लिए "\ t" है।

+0

भागने दृश्यों स्पष्टीकरण के लिए धन्यवाद केवल स्ट्रिंग और चरित्र शाब्दिक में होते हैं। प्रश्न में बैकस्लैश एक स्ट्रिंग या चरित्र शाब्दिक के अंदर नहीं है। –

4

\, जब तुरंत एक नई लाइन के बाद, प्रीप्रोसेसिंग द्वारा उपभोग किया जाता है और अगली "भौतिक" रेखा को वर्तमान तार्किक रेखा में शामिल किया जाता है। यह लंबे समय preprocessing निर्देशों, सभी एक तार्किक लाइन पर होना है जो लिखने के लिए बहुत महत्वपूर्ण है:

#define SHORT very log macro \ 
    consisting of lots and \ 
    lots of preprocessor \ 
    tokens 

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

$ this is \ 
one shell command 

बारे "\n";, कि एक प्राथमिक एक अभिव्यक्ति बयान बनाने के लिए इस्तेमाल अभिव्यक्ति है। सी में, अभिव्यक्तियों को कथन के रूप में उपयोग किया जा सकता है, और इसका हर समय शोषण किया जाता है। उदाहरण के लिए, आपका printf कॉल एक अभिव्यक्ति कथन है। printf("hello world\n") एक पोस्टफिक्स अभिव्यक्ति है जो एक फ़ंक्शन को कॉल करती है, वापसी मूल्य प्राप्त करती है। चूंकि आपने इस अभिव्यक्ति को एक कथन के रूप में उपयोग किया है, इसलिए वापसी मूल्य फेंक दिया जाता है। printf का वापसी मूल्य इंगित करता है कि कितने पात्र मुद्रित किए गए थे, या फिर यह सफल रहा था, इसलिए इसे फेंक कर, आपका प्रोग्राम स्वयं को अनजान कर देता है कि printf कॉल वास्तव में काम करता है या नहीं।

चूंकि अभिव्यक्ति-कथन का मूल्य त्याग दिया गया है, यदि ऐसे कथन का कोई दुष्प्रभाव नहीं है, तो यह एक बेकार बयान है जो कुछ भी नहीं करता है (जैसे आपके "\n")। लेकिन ऐसे बेकार अभिव्यक्ति बयान गलत नहीं हैं। यदि आप अपने कंपाइलर कमांड लाइन में चेतावनी विकल्प जोड़ते हैं तो आपको "चेतावनी के साथ कथन" या ऐसा कुछ चेतावनी मिल सकती है।

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