क्या C और C ++ दोनों में मान्य कोड प्रत्येक भाषा में संकलित होने पर भिन्न व्यवहार उत्पन्न कर सकता है?


664

C और C ++ में कई अंतर हैं, और सभी मान्य C कोड मान्य C ++ कोड नहीं है।
("मान्य" से मेरा मतलब है कि परिभाषित व्यवहार के साथ मानक कोड, यानी कार्यान्वयन-विशिष्ट / अपरिभाषित / आदि नहीं।)

क्या कोई परिदृश्य है जिसमें C और C ++ दोनों में मान्य कोड का एक टुकड़ा प्रत्येक भाषा में एक मानक संकलक के साथ संकलित होने पर अलग व्यवहार का उत्पादन करेगा ?

इसे एक उचित / उपयोगी तुलना बनाने के लिए (मैं व्यावहारिक रूप से उपयोगी कुछ सीखने की कोशिश कर रहा हूं, प्रश्न में स्पष्ट खामियों को खोजने की कोशिश करने के लिए नहीं), चलो मान लेते हैं:

  • प्रीप्रोसेसर-संबंधी (जिसका अर्थ है #ifdef __cplusplus, प्रैग्मस, आदि के साथ कोई हैक नहीं है )
  • कुछ भी कार्यान्वयन-परिभाषित दोनों भाषाओं में समान है (जैसे संख्यात्मक सीमाएं, आदि)
  • हम प्रत्येक मानक के हाल के संस्करणों की तुलना कर रहे हैं (उदाहरण के लिए, C ++ 98 और C90 या बाद
    के संस्करण ) यदि संस्करण बात करते हैं, तो कृपया उल्लेख करें कि प्रत्येक संस्करण कौन से भिन्न व्यवहार का उत्पादन करता है।

11
वैसे, यह एक बोली में प्रोग्राम करने के लिए उपयोगी हो सकता है जो एक ही समय में C और C ++ है। मैंने अतीत में यह किया है और एक वर्तमान परियोजना: TXR भाषा। दिलचस्प बात यह है कि लुआ भाषा के डेवलपर्स ने यही काम किया, और वे इस बोली को "क्लीन सी" कहते हैं। आपको बेहतर संकलन समय और संभवतः C ++ कंपाइलर से अतिरिक्त उपयोगी डायग्नोस्टिक्स का लाभ मिलता है, फिर भी सी पोर्टेबिलिटी को बनाए रखते हैं।
कज़

9
मैंने पुराने सवाल को इस सवाल में मिला दिया क्योंकि इसमें अधिक विचार और उत्तोलित उत्तर हैं। यह अभी भी एक गैर-रचनात्मक प्रश्न का एक उदाहरण है, लेकिन यह हाँ के बाद से काफी सीमा रेखा है, यह SO उपयोगकर्ताओं को कुछ सिखाता है। मर्ज से पहले प्रश्न की स्थिति को प्रतिबिंबित करने के लिए केवल रचनात्मक के रूप में इसे बंद कर रहा हूं। असहमति और फिर से खुला महसूस करें।
जॉर्ज स्टॉकर

13
जैसा कि मुझे लगता है कि इसे फिर से खोलने के लिए मतदान करना, इसका उदाहरण एक "हाँ" के साथ दिया जा सकता है जिसका एक उदाहरण है (जैसा कि नीचे दिया गया है)। मुझे लगता है कि यह रचनात्मक है कि लोग इससे प्रासंगिक व्यवहार सीख सकते हैं।
एंडर्स एबेल

6
@AndersAbel उत्तरों की शुद्ध संख्या, जिनमें से सभी सही हैं, स्पष्ट रूप से प्रदर्शित करता है कि यह एक मेक-इन-लिस्ट प्रश्न बना हुआ है। कोई भी तरीका नहीं था जिससे आप एक सूची प्राप्त किए बिना यह प्रश्न पूछ सकते थे।
dmckee --- पूर्व-मध्यस्थ बिल्ली का बच्चा

2
@ मान्की इसके लायक क्या है, मैं आपसे सहमत हूं। हालाँकि, C ++ टैग लोग हैं ... हम कहेंगे ... feisty
जॉर्ज स्टॉकर

जवाबों:


397

निम्नलिखित, सी और सी में मान्य ++, करने के लिए (सबसे अधिक संभावना) में विभिन्न मूल्यों में परिणाम जा रहा है iसी और C ++:

int i = sizeof('a');

अंतर की व्याख्या के लिए C / C ++ में वर्ण का आकार ('a') देखें ।

इस लेख से एक और :

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}

8
निश्चित रूप से यह एक उम्मीद नहीं थी! मैं कुछ अधिक नाटकीय होने की उम्मीद कर रहा था लेकिन यह अभी भी उपयोगी है, धन्यवाद। :) +1
user541686

17
+1 दूसरा उदाहरण इस तथ्य के लिए एक अच्छा है कि सी ++ को structसंरचनात्मक नामों से पहले की आवश्यकता नहीं है ।
सेठ कार्नेगी

1
@ और मैंने कुछ समय पहले भी ऐसा ही सोचा था और इसका परीक्षण किया था और इसने जीसीसी 4.7.1 पर काम किया था, जो मेरी अपेक्षा के विपरीत था। क्या वह जीसीसी में बग है?
सेठ कार्नेगी

3
@SethCarnegie: एक गैर-अनुरूपता कार्यक्रम को काम करने में विफल होने की आवश्यकता नहीं है, लेकिन यह भी काम करने की गारंटी नहीं है।
एंड्रे विह्रोव

3
struct sz { int i[2];};इसका मतलब यह होगा कि C और C ++ को अलग-अलग मान पैदा करने होंगे। (जबकि आकार डीओ के साथ एक डीएसपी (इंट) == 1, एक ही मूल्य का उत्पादन कर सकता है )।
मार्टिन बोनर

464

यहां एक उदाहरण है जो C और C ++ में फ़ंक्शन कॉल और ऑब्जेक्ट घोषणाओं के बीच अंतर का लाभ उठाता है, साथ ही तथ्य यह है कि C90 अघोषित कार्यों को कॉल करने की अनुमति देता है:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

C ++ में यह कुछ भी प्रिंट नहीं करेगा क्योंकि एक अस्थायी fबनाया और नष्ट हो गया है, लेकिन C90 में यह प्रिंट होगा helloक्योंकि फ़ंक्शन को घोषित किए बिना कॉल किया जा सकता है।

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


7
C के तहत सख्ती से बोलना संकलन नहीं होगा, क्योंकि "int f ()" की घोषणा "int main ()" :) की परिभाषा के बाद है:
Sogartar

15
@ सोगार्टर, सच में? codepad.org/STSQlUhh C99 कंपाइलर आपको एक चेतावनी देगा, लेकिन वे फिर भी आपको इसे संकलित करने देंगे।
१२:२

22
C कार्यों में @Sogartar को स्पष्ट रूप से घोषित करने की अनुमति है।
एलेक्स बी

11
@AlexB C99 और C11 में नहीं।

6
@jrajav वे C99 कंपाइलर नहीं हैं, फिर। एक C99 कंपाइलर एक सिंटैक्स त्रुटि के रूप में अघोषित पहचानकर्ताओं का पता लगाता है। एक कंपाइलर जो ऐसा नहीं करता है वह या तो एक C89 कंपाइलर है, या एक पूर्व-मानक या एक अन्य प्रकार का गैर-अनुरूप कंपाइलर है।

430

C ++ बनाम C90 के लिए, अलग-अलग व्यवहार प्राप्त करने के लिए कम से कम एक तरीका है जिसे परिभाषित नहीं किया गया है। C90 में सिंगल-लाइन टिप्पणियां नहीं हैं। थोड़ी देखभाल के साथ, हम C90 और C ++ में पूरी तरह से अलग परिणामों के साथ एक अभिव्यक्ति बनाने के लिए उपयोग कर सकते हैं।

int a = 10 //* comment */ 2 
        + 3;

C ++ में, //लाइन के अंत तक सब कुछ एक टिप्पणी है, इसलिए यह निम्नानुसार काम करता है:

int a = 10 + 3;

चूंकि C90 में सिंगल-लाइन टिप्पणियां नहीं हैं, केवल /* comment */एक टिप्पणी है। प्रारंभिक के पहले /और पहले 2दोनों भाग हैं, इसलिए यह निम्न पर आता है:

int a = 10 / 2 + 3;

तो, एक सही C ++ कंपाइलर 13 देगा, लेकिन एक सख्ती से सही C90 कंपाइलर 8. निश्चित रूप से, मैंने सिर्फ यहाँ मनमानी संख्याएँ चुनीं - आप अन्य संख्याओं का उपयोग कर सकते हैं जैसा कि आप फिट देखते हैं।


34
WHOA यह दिमाग उड़ाने वाला है !! सभी संभव चीजों में से मैंने कभी नहीं सोचा होगा कि टिप्पणियों का इस्तेमाल व्यवहार में बदलाव के लिए किया जा सकता है। +1
user541686

89
इसके बिना भी 2, यह वैसा ही पढ़ा जाएगा, 10 / + 3जो मान्य (unary +) है।
बेनोइट

12
अब मज़े के लिए, इसे संशोधित करें ताकि C और C ++ दोनों एक ही परिणाम के लिए अलग-अलग अंकगणितीय अभिव्यक्तियों का मूल्यांकन करें।
रयान सी। थॉम्पसन

21
@ रयानहोम्पसन ट्रिवियल। s /
2/1

4
@ मेहरदाद क्या मैं गलत हूं या टिप्पणी पूर्व-संबंधित हैं? इस प्रकार उन्हें आपके प्रश्न के संभावित उत्तर के रूप में बाहर रखा जाना चाहिए! ;-)
अलेउ

179

C90 बनाम C ++ 11 ( intबनाम double):

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

C में autoस्थानीय चर का मतलब है। C90 में वेरिएबल या फंक्शन टाइप को छोड़ना ठीक है। यह करने के लिए चूक int। C ++ 11 में autoकुछ का मतलब पूरी तरह से अलग है, यह संकलक को बताता है कि इसे आरंभ करने के लिए उपयोग किए गए मान से चर के प्रकार का अनुमान लगाया जाए।


10

22
@SethCarnegie: हाँ, यह एक भंडारण वर्ग है; डिफ़ॉल्ट रूप से ऐसा होता है जब आप इसे छोड़ देते हैं, इसलिए किसी ने इसका उपयोग नहीं किया, और उन्होंने इसका अर्थ बदल दिया। मुझे लगता है कि यह intडिफ़ॉल्ट रूप से है। यह चतुर है! +1
user541686

5
सी 11 implicit- नहीं है int
R .. गिटहब स्टॉप हेल्पिंग ICE

23
@KeithThompson आह, मुझे लगता है कि आप अनुमान लगा रहे हैं int। फिर भी, वास्तविक दुनिया में, जहां विरासत कोड के टन हैं और बाजार के नेता ने अभी भी C99 को लागू नहीं किया है और ऐसा करने का कोई इरादा नहीं है, "सी के एक अप्रचलित संस्करण" की बात बेतुका है।
जिम बाल्टर

11
"प्रत्येक चर का एक स्पष्ट भंडारण वर्ग होना चाहिए। आपका सही मायने में, ऊपरी प्रबंधन।"
btown

120

एक और उदाहरण जो मैंने अभी तक नहीं देखा है, यह एक प्रीप्रोसेसर अंतर को उजागर करता है:

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

यह C में "गलत" और C ++ में "सही" प्रिंट करता है - C में, कोई अपरिभाषित मैक्रो 0. का मूल्यांकन करता है। C ++ में, 1 अपवाद है: "true" 1 का मूल्यांकन करता है।


2
दिलचस्प। क्या कोई इस बदलाव के पीछे के तर्क को जानता है?
एंटी

3
क्योंकि "सत्य" एक महत्वपूर्ण शब्द / मान्य मूल्य है, इसलिए इसका मूल्यांकन किसी भी "सच्चे मूल्य" की तरह किया जाता है (इसलिए किसी भी सकारात्मक पूर्णांक की तरह)। आप अभी भी # झूठी को C ++ में "गलत" छापने के लिए सच्चा झूठ
बोल सकते

22
#define true false ಠ_ '
ब्रायन बोएचर

2
@DarioOO यूबी में इस तरह के पुनर्वितरण परिणाम नहीं होगा?
रुस्लान

3
@ डारियोओ: हाँ, आप गलत हैं। कीवर्ड की पुन: परिभाषा की अनुमति नहीं है, भाग्य (यूबी) के लिए छोड़ दिया गया सजा। पूर्वप्रक्रमक संकलन का एक अलग चरण है जो समझ में नहीं आता है।
डेडुप्लिकेटर

108

प्रति C ++ 11 मानक:

ए। अल्पविराम ऑपरेटर सी में लैवल्यू-टू-रेवल्यू रूपांतरण करता है लेकिन सी ++ नहीं:

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

C ++ में इस एक्सप्रेशन का मान 100 होगा और C में यह होगा sizeof(char*)

ख। C ++ में Enumerator का प्रकार उसका Enum है। सी में एन्यूमरेटर का प्रकार इंट है।

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

इसका मतलब है कि sizeof(int)इसके बराबर नहीं हो सकता है sizeof(E)

सी। C ++ में खाली params सूची के साथ घोषित एक फ़ंक्शन कोई तर्क नहीं लेता है। C में खाली params सूची का मतलब है कि फ़ंक्शन params की संख्या और प्रकार अज्ञात है।

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C

पहला भी एलेक्सी की तरह कार्यान्वयन-परिभाषित है। लेकिन +1।
सेठ कार्नेगी

1
@ सेठ, उपरोक्त सभी सामग्री सीधे C ++ 11 मानक के अनुलग्नक C.1 से ली गई है।
किरिल कोबेलेव

हां, लेकिन यह अभी भी कार्यान्वयन-परिभाषित है। sizeof(char*)100 हो सकता है, जिस स्थिति में पहला उदाहरण C और C ++ में एक ही देखने योग्य व्यवहार उत्पन्न करेगा (अर्थात प्राप्त करने का तरीका sअलग sहोगा , 100 होने पर समाप्त हो जाएगा)। ओपी ने उल्लेख किया कि इस प्रकार का कार्यान्वयन-परिभाषित व्यवहार ठीक था क्योंकि वह सिर्फ भाषा-वकील के जवाब से बचना चाहता था, इसलिए पहला अपवाद उसके द्वारा ठीक है। लेकिन किसी भी मामले में दूसरा अच्छा है।
सेठ कार्नेगी

5
एक आसान तय है - बस इसका उदाहरण char arr[sizeof(char*)+1]; int s = sizeof(0, arr);
बदलिए

5
कार्यान्वयन-परिभाषित मतभेदों से बचने के लिए, आप भी उपयोग कर सकते हैं void *arr[100]। इस मामले में एक तत्व एक ही तत्व के लिए एक संकेतक के समान आकार है, इसलिए जब तक 2 या अधिक तत्व होते हैं, सरणी को इसके पहले तत्व के पते से बड़ा होना चाहिए।
फाइननव

53

यह प्रोग्राम 1C ++ और C में प्रिंट करता 0है:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

ऐसा इसलिए होता है क्योंकि double abs(double)C ++ में अधिभार होता है , इसलिए C में abs(0.6)लौटते 0.6समय, लौटने 0से पहले अंतर्निहित डबल-टू-इंट रूपांतरण के कारण वापस लौटता है int abs(int)। सी में, आपको fabsकाम करने के लिए उपयोग करना होगा double


5
उस मुद्दे के साथ किसी और के कोड को डीबग करना पड़ा। ओह मैं कैसे प्यार करता था। वैसे भी आपका प्रोग्राम C ++ में भी 0 छाप रहा है। C ++ को हेडर "cmath" का उपयोग करना है, पहले एक रिटर्न की तुलना देखें 0 ideone.com/0tQB2G 2 में से एक की वापसी 1 ideone.com/SLeANo
CoffeDeveloper

ख़ुशी / खेद है कि मैं केवल डिबगिंग के माध्यम से इस अंतर को खोजने वाला नहीं हूं। वीएस २०१३ में अभी परीक्षण किया गया है, इस सामग्री के साथ केवल फ़ाइल के साथ एक खाली 1 आउटपुट होगा यदि एक्सटेंशन .cpp है, और 0 यदि एक्सटेंशन .c है। ऐसा लगता है कि <math.h> को अप्रत्यक्ष रूप से VS में शामिल किया गया है।
पावल चिकुलाव

और वीएस सी ++ में दिखता है, <math.h> में वैश्विक नाम स्थान में सी ++ सामान शामिल है, जहां जीसीसी के लिए यह नहीं है। हालांकि यह मानक व्यवहार नहीं है।
पावल चिकुलाव

2
यह विशेष कोड नमूना कार्यान्वयन-निर्भर है: stdlib.hकेवल परिभाषित करता है abs(int)और abs(long); संस्करण abs(double)द्वारा घोषित किया गया है math.h। इसलिए यह प्रोग्राम अभी भी abs(int)संस्करण को कॉल कर सकता है । यह एक कार्यान्वयन विवरण है कि क्या इसमें शामिल होने का stdlib.hकारण भी है math.h। (मुझे लगता है कि अगर abs(double)यह कहा जाता है तो यह एक बग होगा , लेकिन अन्य एस्पेक्ट math.hको शामिल नहीं किया गया था)।
एमएम

1
एक माध्यमिक मुद्दा यह है कि यद्यपि C ++ मानक यह कहता दिखाई देता है कि इसमें <math.h>अतिरिक्त अधिभार भी शामिल हैं; व्यवहार में यह पता चला है कि सभी प्रमुख संकलक उन ओवरलोड को शामिल नहीं करते हैं जब तक कि फार्म <cmath>का उपयोग नहीं किया जाता है।
एमएम

38
#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

सी में, यह sizeof(int)मौजूदा सिस्टम पर जो कुछ भी है, उसे प्रिंट करता है, जो कि आमतौर पर 4आज के समय में आमतौर पर इस्तेमाल होने वाले ज्यादातर सिस्टम में होता है।

C ++ में, यह 1 प्रिंट करना होगा।


3
हां, मैं वास्तव में इस ट्रिक से परिचित था, क्योंकि 'C' C में एक int है, और C ++ में एक चार है, लेकिन इसे यहां सूचीबद्ध करना अभी भी अच्छा है।
शॉन

9
यह एक दिलचस्प साक्षात्कार प्रश्न बना देगा - विशेष रूप से ऐसे लोगों के लिए जो अपने CV पर c / c ++ विशेषज्ञ डालते हैं
मार्टिन बेकेट

2
हालांकि अंडरहैंड की तरह। Sizeof का पूरा उद्देश्य यह है कि आपको यह जानने की आवश्यकता नहीं है कि एक प्रकार कितना बड़ा है।
दाना साने

13
C में मूल्य कार्यान्वयन परिभाषित है और 1 एक संभावना है। (सी ++ में इसे 1 में बताया गया है।)
विंडोज प्रोग्रामर

3
वास्तव में इसका दोनों मामलों में अपरिभाषित व्यवहार है। %dके लिए सही प्रारूप निर्दिष्ट नहीं है size_t
आर .. गिटहब स्टॉप हेल्पिंग ICE

37

एक और sizeofजाल: बूलियन अभिव्यक्ति।

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

यह sizeof(int)C के बराबर है, क्योंकि अभिव्यक्ति प्रकार की है int, लेकिन आम तौर पर C ++ में 1 है (हालांकि इसकी आवश्यकता नहीं है)। व्यवहार में वे लगभग हमेशा अलग होते हैं।


6
एक !एक के लिए पर्याप्त होना चाहिए bool
एलेक्सी फ्रुंज़े

4
!! बूलियन रूपांतरण ऑपरेटर के लिए
अंतर है

1
sizeof(0)है 4दोनों C और C ++ में क्योंकि 0एक पूर्णांक rvalue है। sizeof(!0)है 4सी में और 1सी ++ में। लॉजिकल टाइप बूल के ऑपरेंड पर संचालित नहीं होता है। यदि इंट वैल्यू है , तो इसे 0अंतर्निहित रूप से false(एक बूल रिवल्यू) में बदल दिया जाता है , फिर इसे फ़्लिप किया जाता है, जिसके परिणामस्वरूप true। दोनों trueऔर falseC ++ bool rvalues कर रहे हैं और sizeof(bool)है 1। हालाँकि C में !0मूल्यांकन होता है 1, जो कि प्रकार int का एक प्रकार है। C प्रोग्रामिंग भाषा में डिफ़ॉल्ट रूप से कोई बूल डेटा प्रकार नहीं है।
गैलेक्सी

26

C ++ प्रोग्रामिंग लैंग्वेज (तीसरा संस्करण) तीन उदाहरण देता है:

  1. sizeof ('a'), जैसा कि @Adam Rosenfield ने उल्लेख किया है;

  2. // छिपा कोड बनाने के लिए उपयोग की जा रही टिप्पणियाँ:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
  3. संरचनाएं इत्यादि सामानों को अपने उदाहरण के अनुसार, बाहर की तरफ स्कैप्स में छिपा दें।



21

C ++ मानक द्वारा सूचीबद्ध एक और:

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}

तो आप गद्दी मतभेद मिलता है?
v.oddou

आह क्षमा करें, मुझे यह मिल गया, xशीर्ष पर एक और है। मुझे लगा कि आपने "सरणी a" कहा है।
v.oddou

20

C डिफ़ॉल्ट में बाह्य फ़ंक्शन में इनलाइन फ़ंक्शंस जहां C ++ में वे नहीं हैं।

निम्नलिखित दो फाइलों को एक साथ संकलित करने से जीएनयू सी के मामले में "मैं इनलाइन हूं" प्रिंट होगा लेकिन सी ++ के लिए कुछ भी नहीं।

फ़ाइल 1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

फाइल 2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

इसके अलावा, C ++ किसी भी constवैश्विक व्यवहार करता है staticजब तक कि स्पष्ट रूप से घोषित नहीं किया जाता है extern, सी के विपरीत जिसमें externडिफ़ॉल्ट है।


मैं वास्तव में ऐसा नहीं सोचता। संभवत: आप बिंदु से चूक गए हैं। यह स्ट्रक्चर सेंट की परिभाषा के बारे में नहीं है जो केवल कोड को वैध बनाने के लिए उपयोग किया जाता है c ++। मुद्दा यह है कि यह सी बनाम सी ++ में इनलाइन कार्यों के विभिन्न व्यवहार को उजागर करता है। वही बाह्य पर लागू होता है। इनमें से किसी भी समाधान पर चर्चा नहीं की गई है।
fkl

2
इनलाइन फ़ंक्शंस का अलग-अलग व्यवहार क्या है और externइसे यहाँ दिखाया गया है?
सेठ कार्नेगी

यह बहुत स्पष्ट रूप से लिखा गया है। "इनलाइन फ़ंक्शंस इन सी डिफॉल्ट टू एक्सटर्नल स्कोप जहाँ सी + + में वे नहीं हैं (कोड से पता चलता है कि)। साथ ही सी ++ किसी भी कॉस्ट ग्लोबल को फ़ाइल स्कोप के रूप में मानता है जब तक कि इसे स्पष्ट रूप से एक्सटर्नल घोषित नहीं किया जाता है, सी के विपरीत जिसमें एक्सट्रीम डिफॉल्ट होता है। एक समान है। उदाहरण के लिए बनाया जा सकता है कि "। मैं हैरान हूँ - क्या यह समझ में नहीं आ रहा है?
fkl

12
@fayyazkl दिखाया गया व्यवहार केवल लुकअप ( struct funबनाम fn) के अंतर के कारण है और इसमें कुछ भी नहीं है कि फ़ंक्शन इनलाइन है या नहीं। यदि आप inlineक्वालीफायर निकालते हैं तो परिणाम समान है ।
एलेक्स बी

3
आईएसओ सी में यह कार्यक्रम बीमार है: inlineC99 तक जोड़ा नहीं गया था, लेकिन C99 में fun()इसे एक दायरे में प्रोटोटाइप के बिना नहीं कहा जा सकता है। इसलिए मुझे लगता है कि यह उत्तर केवल GNU C.
MM

16
struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

C ++ में 0 या C में 3 के एक्जिट कोड के साथ रिटर्न

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

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

VC ++ 2005 ने यह संकलित करने से इनकार कर दिया कि C ++ मोड में, हालांकि, "निकास कोड" को फिर से परिभाषित करने के बारे में शिकायत की गई थी। (मुझे लगता है कि यह एक कंपाइलर बग है, जब तक कि मैं अचानक प्रोग्राम करने के लिए कैसे भूल गया हूं।) सी के रूप में संकलित होने पर यह 1 के एक प्रोसेस एक्जिट कोड के साथ बाहर निकल गया।


बाहर निकलने का उपयोग कर आपका दूसरा उदाहरण, gcc या g ++ पर संकलित नहीं है, दुर्भाग्य से। हालांकि यह एक अच्छा विचार है।
शॉन

1
exit(code)जाहिरा तौर पर एक codeप्रकार के चर की वैध घोषणा है exit। ("सबसे अधिक डरावने पार्स" देखें, जो एक अलग लेकिन समान मुद्दा है)।
user253751

16
#include <stdio.h>

struct A {
    double a[32];
};

int main() {
    struct B {
        struct A {
            short a, b;
        } a;
    };
    printf("%d\n", sizeof(struct A));
    return 0;
}

यह प्रोग्राम प्रिंट करता है 128( 32 * sizeof(double)) जब C ++ कंपाइलर 4का उपयोग करके संकलित किया जाता है और जब C कंपाइलर का उपयोग करके संकलित किया जाता है।

ऐसा इसलिए है क्योंकि सी में गुंजाइश रिज़ॉल्यूशन की धारणा नहीं है। अन्य संरचनाओं में निहित सी संरचनाओं में बाहरी संरचना के दायरे में डाल दिया जाता है।


यह एक दिलचस्प है! (मुझे लगता है कि आप 32*sizeof(double)32 के बजाय मतलब है :))
user1354557

3
नोट आपके द्वारा यूबी हो रही है कि मुद्रण size_tके साथ%d
phuclv

7

C और C ++ वैश्विक नामस्थान के बीच के अंतर को न भूलें। मान लीजिए कि आपके पास एक foo.cpp है

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

और एक foo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

अब मान लीजिये आपके पास एक main.c और main.cpp है जो दोनों इस तरह दिखते हैं:

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

जब C ++ के रूप में संकलित किया जाता है, तो यह C ++ वैश्विक नामस्थान में प्रतीक का उपयोग करेगा; सी में यह सी का उपयोग करेगा:

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C

आप लिंकेज विनिर्देश मतलब है?
user541686

नामकरण। C ++ नामों में उपसर्ग और प्रत्यय होते हैं जबकि C नहीं
CoffeDeveloper

नाम मैनलिंग C ++ विनिर्देशन का हिस्सा नहीं है। क्या यह C में निषिद्ध है?
आसमान छू रहा है

5
यह अपरिभाषित व्यवहार (एकाधिक परिभाषा foo) है। अलग-अलग "वैश्विक नामस्थान" नहीं हैं।
एमएम

4
int main(void) {
    const int dim = 5; 
    int array[dim];
}

बल्कि यह अजीब है कि यह C ++ और C99, C11, और C17 में मान्य है (हालांकि C11, C17 में वैकल्पिक); लेकिन C89 में मान्य नहीं है।

C99 + में यह एक वैरिएबल-लेंथ एरे बनाता है, जिसमें सामान्य सरणियों की अपनी ख़ासियत होती है, क्योंकि इसमें कंपाइल-टाइम टाइप के बजाय रनटाइम टाइप होता है, और sizeof arrayC में पूर्णांक स्थिर अभिव्यक्ति नहीं होती है। C ++ में टाइप पूरी तरह से स्थिर होता है।


यदि आप यहां इनिशियलाइज़र जोड़ने का प्रयास करते हैं:

int main(void) {
    const int dim = 5; 
    int array[dim] = {0};
}

C ++ मान्य है, लेकिन C नहीं, क्योंकि वैरिएबल-लेंथ सरणियों में इनिशियलाइज़र नहीं हो सकता है।


0

यह C और C ++ में अंतराल और अंतराल की चिंता करता है।

C प्रोग्रामिंग लैंग्वेज में, प्री-इन्क्रीमेंट और पोस्ट-इन्क्रीमेंट ऑपरेटर्स, दोनों रिवल्यूशन लौटाते हैं, लैवल नहीं। इसका अर्थ है कि वे =असाइनमेंट ऑपरेटर के बाईं ओर नहीं हो सकते हैं । ये दोनों कथन C में संकलक त्रुटि देंगे:

int a = 5;
a++ = 2;  /* error: lvalue required as left operand of assignment */
++a = 2;  /* error: lvalue required as left operand of assignment */

C ++ में, हालांकि प्री-इन्क्रीमेंट ऑपरेटर एक लैवल्यू लौटाता है , जबकि पोस्ट-इन्क्रीमेंट ऑपरेटर एक रिवॉल्यू लौटाता है। इसका मतलब है कि पूर्व-वेतन वृद्धि ऑपरेटर के साथ एक अभिव्यक्ति =असाइनमेंट ऑपरेटर के बाईं ओर रखी जा सकती है !

int a = 5;
a++ = 2;  // error: lvalue required as left operand of assignment
++a = 2;  // No error: a gets assigned to 2!

अब ऐसा क्यों है? पोस्ट-इन्क्रीमेंट वेरिएबल को बढ़ाता है, और यह वैरिएबल वैसा ही लौटाता है जैसा कि इन्क्रीमेंट से पहले था । यह वास्तव में सिर्फ एक प्रतिद्वंद्विता है। चर का पूर्व मान एक अस्थायी के रूप में एक रजिस्टर में कॉपी किया जाता है, और फिर एक वृद्धि होती है। लेकिन एक का पूर्व मान अभिव्यक्ति द्वारा लौटाया जाता है, यह एक प्रतिद्वंद्विता है। यह अब चर की वर्तमान सामग्री का प्रतिनिधित्व नहीं करता है।

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

int x = a;
int x = ++a;

चूंकि पूर्व वेतन वृद्धि एक प्रतिफल देती है, इसलिए हम इसे कुछ भी प्रदान कर सकते हैं। निम्नलिखित दो कथन समान हैं। दूसरे असाइनमेंट में, पहले एक वेतन वृद्धि की जाती है, फिर उसका नया मान 2 के साथ ओवरराइट किया जाता है।

int a;
a = 2;
++a = 2;  // Valid in C++.

3
यहाँ कोई "C में मान्य" नहीं है।
o11c

0

खाली संरचनाओं का आकार C में 0 और C ++ में 1 है:

#include <stdio.h>

typedef struct {} Foo;

int main()
{
    printf("%zd\n", sizeof(Foo));
    return 0;
}

1
नहीं, अंतर यह है कि सी में खाली संरचनाएं नहीं हैं, सिवाय एक संकलक विस्तार के, अर्थात यह कोड "C और C ++ दोनों में मान्य नहीं है"
एंटी हवाला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.