सी / सी ++ में लोगों द्वारा किए गए अनुचित मान्यताओं को प्रदर्शित करने के लिए एक शैक्षिक उपकरण में क्या है?


121

मैं SO के लिए एक छोटा सा शैक्षिक उपकरण तैयार करना चाहता हूं, जो शुरुआती (और मध्यवर्ती) प्रोग्रामर को C, C ++ और उनके प्लेटफार्मों में उनकी अनुचित मान्यताओं को पहचानने और चुनौती देने में मदद करे।

उदाहरण:

  • "पूर्णांक चारों ओर लपेटते हैं"
  • "सभी के पास ASCII है"
  • "मैं एक फंक्शन पॉइंटर को शून्य में स्टोर कर सकता हूं *"

मुझे लगा कि एक छोटा सा परीक्षण कार्यक्रम विभिन्न प्लेटफार्मों पर चलाया जा सकता है, जो "प्रशंसनीय" धारणाओं को चलाता है, जो एसओ में हमारे अनुभव से हैं, आमतौर पर कई अनुभवहीन / अर्ध-अनुभवी मुख्यधारा डेवलपर्स द्वारा बनाए गए हैं और विविध मशीनों के टूटने के तरीकों को रिकॉर्ड करते हैं।

इसका लक्ष्य यह साबित करना नहीं है कि यह कुछ करने के लिए "सुरक्षित" है (जो करना असंभव होगा, परीक्षण केवल कुछ भी साबित करते हैं यदि वे टूटते हैं), लेकिन इसके बजाय यहां तक कि सबसे असुविधाजनक व्यक्ति को प्रदर्शित करने के लिए कि कैसे सबसे असंगत अभिव्यक्ति है एक अलग मशीन पर टूट, अगर यह एक अपरिभाषित या कार्यान्वयन परिभाषित व्यवहार है।

इसे प्राप्त करने के लिए मैं आपसे पूछना चाहता हूं:

  • इस विचार को कैसे सुधारा जा सकता है?
  • कौन सा परीक्षण अच्छा होगा और उन्हें कैसा दिखना चाहिए?
  • क्या आप उन प्लेटफार्मों पर परीक्षण चलाएंगे जिन पर आप अपना हाथ रख सकते हैं और परिणाम पोस्ट कर सकते हैं, ताकि हम प्लेटफार्मों के डेटाबेस के साथ समाप्त हो जाएं, वे कैसे भिन्न होते हैं और इस अंतर की अनुमति क्यों है?

यहाँ परीक्षण खिलौना के लिए वर्तमान संस्करण है:

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
int count=0;
int total=0;
void expect(const char *info, const char *expr)
{
    printf("..%s\n   but '%s' is false.\n",info,expr);
    fflush(stdout);
    count++;
}
#define EXPECT(INFO,EXPR) if (total++,!(EXPR)) expect(INFO,#EXPR)

/* stack check..How can I do this better? */
ptrdiff_t check_grow(int k, int *p)
{
    if (p==0) p=&k;
    if (k==0) return &k-p;
    else return check_grow(k-1,p);
}
#define BITS_PER_INT (sizeof(int)*CHAR_BIT)

int bits_per_int=BITS_PER_INT;
int int_max=INT_MAX;
int int_min=INT_MIN;

/* for 21 - left to right */
int ltr_result=0;
unsigned ltr_fun(int k)
{
    ltr_result=ltr_result*10+k;
    return 1;
}

int main()
{
    printf("We like to think that:\n");
    /* characters */
    EXPECT("00 we have ASCII",('A'==65));
    EXPECT("01 A-Z is in a block",('Z'-'A')+1==26);
    EXPECT("02 big letters come before small letters",('A'<'a'));
    EXPECT("03 a char is 8 bits",CHAR_BIT==8);
    EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);

    /* integers */
    EXPECT("05 int has the size of pointers",sizeof(int)==sizeof(void*));
    /* not true for Windows-64 */
    EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));

    EXPECT("06 integers are 2-complement and wrap around",(int_max+1)==(int_min));
    EXPECT("07 integers are 2-complement and *always* wrap around",(INT_MAX+1)==(INT_MIN));
    EXPECT("08 overshifting is okay",(1<<bits_per_int)==0);
    EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);
    {
        int t;
        EXPECT("09a minus shifts backwards",(t=-1,(15<<t)==7));
    }
    /* pointers */
    /* Suggested by jalf */
    EXPECT("10 void* can store function pointers",sizeof(void*)>=sizeof(void(*)()));
    /* execution */
    EXPECT("11 Detecting how the stack grows is easy",check_grow(5,0)!=0);
    EXPECT("12 the stack grows downwards",check_grow(5,0)<0);

    {
        int t;
        /* suggested by jk */
        EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));
    }
    {
        /* Suggested by S.Lott */
        int a[2]={0,0};
        int i=0;
        EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));
    }
    {
        struct {
            char c;
            int i;
        } char_int;
        EXPECT("15 structs are packed",sizeof(char_int)==(sizeof(char)+sizeof(int)));
    }
    {
        EXPECT("16 malloc()=NULL means out of memory",(malloc(0)!=NULL));
    }

    /* suggested by David Thornley */
    EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));
    /* this is true for C99, but not for C90. */
    EXPECT("18 a%b has the same sign as a",((-10%3)==-1) && ((10%-3)==1));

    /* suggested by nos */
    EXPECT("19-1 char<short",sizeof(char)<sizeof(short));
    EXPECT("19-2 short<int",sizeof(short)<sizeof(int));
    EXPECT("19-3 int<long",sizeof(int)<sizeof(long));
    EXPECT("20 ptrdiff_t and size_t have the same size",(sizeof(ptrdiff_t)==sizeof(size_t)));
#if 0
    {
        /* suggested by R. */
        /* this crashed on TC 3.0++, compact. */
        char buf[10];
        EXPECT("21 You can use snprintf to append a string",
               (snprintf(buf,10,"OK"),snprintf(buf,10,"%s!!",buf),strcmp(buf,"OK!!")==0));
    }
#endif

    EXPECT("21 Evaluation is left to right",
           (ltr_fun(1)*ltr_fun(2)*ltr_fun(3)*ltr_fun(4),ltr_result==1234));

    {
    #ifdef __STDC_IEC_559__
    int STDC_IEC_559_is_defined=1;
    #else 
    /* This either means, there is no FP support
     *or* the compiler is not C99 enough to define  __STDC_IEC_559__
     *or* the FP support is not IEEE compliant. */
    int STDC_IEC_559_is_defined=0;
    #endif
    EXPECT("22 floating point is always IEEE",STDC_IEC_559_is_defined);
    }

    printf("From what I can say with my puny test cases, you are %d%% mainstream\n",100-(100*count)/total);
    return 0;
}

ओह, और मैंने शुरू से ही इस समुदाय को विकी बना दिया क्योंकि मुझे लगा कि जब वे इसे पढ़ते हैं तो लोग मेरे ब्लॅबर को संपादित करना चाहते हैं।

अद्यतन आपके इनपुट के लिए धन्यवाद। मैंने आपके उत्तरों में से कुछ मामले जोड़े हैं और मैं देखूंगा कि क्या ग्रेग ने सुझाव दिया है कि मैं इसके लिए एक गिथब स्थापित कर सकता हूं।

अद्यतन : मैंने इसके लिए एक github रेपो बनाया है, फ़ाइल "gotcha.c" है:

कृपया पैच या नए विचारों के साथ यहां जवाब दें, इसलिए उन्हें यहां चर्चा या स्पष्ट किया जा सकता है। मैं उन्हें फिर gotcha.c में विलीन कर दूंगा।


7
डॉस में मध्यम मॉडल पर विचार करें। फ़ंक्शन कई खंडों में संग्रहीत किए जा सकते हैं, इसलिए एक फ़ंक्शन पॉइंटर 32 बिट लंबा है। लेकिन आपका डेटा केवल एक सेगमेंट में संग्रहीत किया जाता है, इसलिए डेटा पॉइंटर्स केवल 16 बिट लंबे होते हैं। चूंकि void * एक डेटा पॉइंटर है, यह 16 बिट्स चौड़ा है, इसलिए आप एक फंक्शन पॉइंटर को एक में फिट नहीं कर सकते हैं। C-jump.com/CIS77/ASM/Directives/D77_0030_models.htm देखें ।
डेविड

6
शायद आप इस कोड को github.com या कुछ और पर फेंक सकते हैं और फिर लोग आसानी से पैच योगदान कर सकते हैं।
ग्रेग हेविगेल

1
यहां बहुत सी चीजें मदद करनी चाहिए: stackoverflow.com/questions/367633/…
मार्टिन यॉर्क

4
POSIX के लिए आवश्यक है कि फ़ंक्शन पॉइंटर्स में शून्य * के समान प्रतिनिधित्व हो और सूचना के नुकसान के बिना इसे एक कास्ट के साथ परिवर्तित किया जा सके। इसका एक कारण यह है कि dlsym()एक शून्य * लौटता है, लेकिन डेटा और फ़ंक्शन दोनों के लिए अभिप्रेत है। इसलिए इस पर निर्भर रहना इतना बुरा नहीं हो सकता है।
19

3
@ ट्रिस्टोपिया: प्वाइंट 15 यहां है, क्योंकि कई शुरुआती लोग अक्सर यह जानकर हैरान हो जाते हैं कि डेटा लगातार पैक नहीं किया जाता है, बल्कि कुछ सीमाओं से जुड़ा होता है। जब वे सदस्य आदेश बदलते हैं और विभिन्न ऑब्जेक्ट आकार प्राप्त करते हैं, तो वे हैरान रह जाते हैं। इसके अलावा, पैकिंग कई समकालीन सूक्ष्म नियंत्रक या एम्बेडेड उपकरणों के साथ डिफ़ॉल्ट मोड है। मेरा AVR Atmega और TurboC / MSDOS आउटपुट भी पैक है। MSDOS अभी भी औद्योगिक अनुप्रयोगों में उपयोग किया जाता है।
नॉर्डिक मेनफ्रेम

जवाबों:


91

सहित सबएक्सप्रेस के मूल्यांकन का क्रम

  • फ़ंक्शन कॉल के तर्क और
  • ऑपरेटरों की ऑपरेंड (जैसे, +, -, =, *, /), के अपवाद के साथ:
    • द्विआधारी तार्किक ऑपरेटरों ( &&और ||),
    • ternary सशर्त ऑपरेटर ( ?:), और
    • अल्पविराम ऑपरेटर ( ,)

है अनिर्दिष्ट

उदाहरण के लिए

  int Hello()
  {
       return printf("Hello"); /* printf() returns the number of 
                                  characters successfully printed by it
                               */
  }

  int World()
  {
       return printf("World !");
  }

  int main()
  {

      int a = Hello() + World(); //might print Hello World! or World! Hello
      /**             ^
                      | 
                Functions can be called in either order
      **/
      return 0;
  } 

1
मुझे हमेशा से पता था कि फंक्शन पैरामीटर्स के बारे में, लेकिन मैंने इसे ऑपरेटर्स के संदर्भ में कभी नहीं सोचा था। ... और अगर मैंने कभी आपको प्रोडक्शन के माहौल में ऐसा कोड लिखते देखा तो मैं आपको गीले नूडल से थप्पड़ मार दूंगा।
रिवलॉक

3
@ बिली: लेकिन केवल ऑपरेटरों के आदिम संस्करणों के लिए।
डेनिस ज़िकफोज़

1
@ डेनिस: यह सच है। (यही कारण है कि यह प्रभावी / MoreEffective C ++ में एक आइटम है जो उन पर कभी भी अधिभार नहीं डालते हैं (जब तक कि आप लिख नहीं रहे हैं boost::spirit)
बिली ओनली

1
@ डैनियल: मुझे यकीन नहीं है कि आप क्या कहना चाह रहे हैं। ऐसा लगता है कि आप ऑपरेटरों को ओवरलोड करने के लिए इसका ठीक सुझाव दे रहे हैं क्योंकि इसकी केवल आपके वर्ग के उपयोगकर्ता जो इसे गलत कर सकते हैं, और यदि आप सीधे C ++ में नहीं लिख रहे हैं तो कोई बात नहीं। जिसका कोई मतलब नहीं है।
डेनिस ज़िकफोज़

2
@ user420536: व्यवहार सिर्फ अनिर्दिष्ट है लेकिन अपरिभाषित नहीं है। हाँ उदाहरण या तो हैलो वर्ल्ड प्रिंट कर सकते हैं! या दुनिया! हैलो, लेकिन यह सिर्फ अनिर्दिष्ट है क्योंकि +ऑपरेटर के संचालन के मूल्यांकन का क्रम अनिर्दिष्ट है (कम्पाइलर लेखकों को व्यवहार का दस्तावेज नहीं चाहिए)। यह किसी भी अनुक्रम बिंदु नियम का उल्लंघन नहीं करता है ।
प्रसून सौरव

38

sdcc 29.7 / ucSim / Z80

We like to think that:
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..19-2 short<int
   but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
   but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
From what I can say with my puny test cases, you are Stop at 0x0013f3: (106) Invalid instruction 0x00dd

प्रिंटफ क्रैश। "O_O"


gcc 4.4@x86_64-suse-linux

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 79% mainstream

gcc 4.4@x86_64-suse-linux (-O2)

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 82% mainstream

क्लेंग 2.7@x86_64-suse-linux

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 72% mainstream

open64 4.2.3@x86_64-suse-linux

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 75% mainstream

इंटेल 11.1@x86_64-suse-linux

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..21a Function Arguments are evaluated right to left
but '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.
ltr_result is 1234 in this case
..26 sizeof() does not evaluate its arguments
but '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.
From what I can say with my puny test cases, you are 75% mainstream

टर्बो सी ++ / डॉस / स्मॉल मेमोरी

We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 81% mainstream

टर्बो सी ++ / डॉस / मीडियम मेमोरी

We like to think that:
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..10 void* can store function pointers
but 'sizeof(void*)>=sizeof(void(*)())' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 78% mainstream

टर्बो सी ++ / डॉस / कॉम्पैक्ट मेमोरी

We like to think that:
..05 int has the size of pointers
but 'sizeof(int)==sizeof(void*)' is false.
..09a minus shifts backwards
but '(t=-1,(15<<t)==7)' is false.
..16 malloc()=NULL means out of memory
but '(malloc(0)!=NULL)' is false.
..19-2 short<int
but 'sizeof(short)<sizeof(int)' is false.
..20 ptrdiff_t and size_t have the same size
but '(sizeof(ptrdiff_t)==sizeof(size_t))' is false.
..22 floating point is always IEEE
but 'STDC_IEC_559_is_defined' is false.
..25 pointer arithmetic works outside arrays
but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.
..25a pointer arithmetic works outside arrays
but '(diff=&p1-&p2, &p2+diff==&p1)' is false.
From what I can say with my puny test cases, you are 75% mainstream

cl65 @ कमोडोर पीईटी (वाइस एम्यूलेटर)

वैकल्पिक शब्द


मैं इन्हें बाद में अपडेट करूंगा:


विंडोज XP पर बोरलैंड सी ++ बिल्डर 6.0

..04 a char is signed
   but 'CHAR_MIN==SCHAR_MIN' is false.
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
   but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..16 malloc()=NULL means out of memory
   but '(malloc(0)!=NULL)' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 71% mainstream

विजुअल स्टूडियो एक्सप्रेस 2010 सी ++ सीएलआर, विंडोज 7 64 बिट

(C ++ के रूप में संकलित किया जाना चाहिए क्योंकि CLR संकलक शुद्ध C का समर्थन नहीं करता है)

We like to think that:
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream

MINGW64 (gcc-4.5.2 प्रीलेलेस)

- http://mingw-w64.sourceforge.net/

We like to think that:
..05 int has the size of pointers
   but 'sizeof(int)==sizeof(void*)' is false.
..05a long has at least the size of pointers
   but 'sizeof(long)>=sizeof(void*)' is false.
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
   but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 67% mainstream

64 बिट विंडोज LLP64 मॉडल का उपयोग करता है: दोनों को intऔर long32-बिट के रूप में परिभाषित किया गया है, जिसका अर्थ है कि न तो एक पॉइंटर के लिए पर्याप्त है।


avr-gcc 4.3.2 / ATmega168 (Arduino Diecimila)

असफल धारणाएँ हैं:

..14 i++ is structly left to right
..16 malloc()=NULL means out of memory
..19-2 short<int
..21 Evaluation is left to right
..22 floating point is always IEEE

Atmega168 में 16 बिट पीसी है, लेकिन कोड और डेटा अलग-अलग एड्रेस स्पेस में हैं। बड़ा Atmegas एक 22 बिट पीसी है !।


MacOSX 10.6 पर gcc 4.2.1, -पीसी पीपीसी के साथ संकलित

We like to think that:
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits come always first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream


32
और आपने एक और धारणा की पहचान की है: कि आप एक टर्मिनल लाइन पर 80 अक्षर फिट कर सकते हैं।
माइक सेमोर

3
sizeof(void*)>=sizeof(void(*)())== से अधिक प्रासंगिक होगा। हम सभी के बारे में परवाह तो इस धारणा आप परीक्षण करने की जरूरत है कि क्या एक है, "हम एक शून्य सूचक में एक समारोह सूचक स्टोर कर सकते हैं" है void*है कम से कम एक समारोह सूचक के रूप में बड़ा के रूप में।
जुलफ

1
यदि आपका वातावरण POSIX-compliant है, तो आपको ठीक होना चाहिए sizeof(void*)>=sizeof(void(*)())- opengroup.org/onlinepubs/009695399/functions/dlsym.html
डैनियल

26

बहुत समय पहले, मैं एक पाठ्यपुस्तक से सी पढ़ा रहा था जो कि थी

printf("sizeof(int)=%d\n", sizeof(int));

एक नमूना सवाल के रूप में। यह एक छात्र के लिए विफल हो गया, क्योंकि sizeofप्रकार के मूल्यों को जन्म देता हैsize_t , नहीं int, intइस कार्यान्वयन पर 16 बिट था और size_t32 था, और यह बड़े endian था। (मंच 680x0-आधारित मैकिंटॉश पर लाइट्सपीड सी था। मैंने कहा कि यह एक लंबा समय था)।


7
+1 सबसे आम, और आमतौर पर अनदेखी, इस तरह की त्रुटियों को इंगित करने के लिए।
आर .. गिटहब स्टॉप हेल्पिंग ICE

4
यह 64-बिट सिस्टम पर भी होता है, जहां size_t 64 बिट है और इनट्स लगभग हमेशा छोटे होते हैं। Win64 अभी भी अजीब है, क्योंकि size_t एक unsigned long longहै। टेस्ट 17 के रूप में जोड़ा गया।
नॉर्डिक मेनफ्रेम

दुर्भाग्य से, माइक्रोसॉफ्ट का सी रनटाइम आकार पूर्णांक के zलिए संशोधक का समर्थन नहीं करता है size_t, और long longकुछ प्लेटफार्मों पर भी समर्थित नहीं है। इसलिए किसी वस्तु के मुद्रित आकार को प्रारूपित करने या डालने का कोई सुरक्षित पोर्टेबल तरीका नहीं है।
फिल मिलर

15

आपको उन लोगों ++और --मान्यताओं को शामिल करना होगा जो लोग बनाते हैं।

a[i++]= i;

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

कोई भी कथन जिसमें ++(या --) और एक चर है जो एक से अधिक बार होता है एक समस्या है।


और यह सिर्फ इतना आम सवाल भी है!
मैथ्यू एम।

8

बहुत ही रोचक!

अन्य चीजें जो मैं सोच सकता हूं, उनके लिए जाँच करना उपयोगी हो सकता है:

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

  • यदि आप एक NULL डेटा पॉइंटर लेते हैं और उसे उपयुक्त पूर्णांक प्रकार में डालते हैं, तो क्या इसका संख्यात्मक मान 0 है? (कुछ वास्तव में प्राचीन मशीनों पर टूटता है --- देखें http://c-faq.com/null/machexamp.html ।) सूचक के साथ डिट्टो। साथ ही, वे अलग-अलग मूल्य हो सकते हैं।

  • क्या एक पॉइंटर को उसके संबंधित स्टोरेज ऑब्जेक्ट के अंत में बढ़ाता है, और फिर वापस फिर से, समझदार परिणाम देता है? (मुझे नहीं पता है कि यह वास्तव में टूटता है, लेकिन मुझे लगता है कि सी युक्ति आपको उन बिंदुओं के बारे में सोचने की अनुमति नहीं देती है जो या तो इंगित नहीं करते हैं (क) किसी सरणी की सामग्री या (बी) तत्व सरणी के तुरंत बाद या (c) NULL। http://c-faq.com/aryptr/non0based.com ) देखें ।

  • दो अलग-अलग स्टोरेज ऑब्जेक्ट्स के साथ दो बिंदुओं की तुलना करता है <और> लगातार परिणाम उत्पन्न करते हैं? (मैं कल्पना कर सकता हूं कि यह विदेशी सेगमेंट-आधारित मशीनों पर ब्रेकिंग है; कल्पना इस तरह की तुलना करने से मना करती है, इसलिए कंपाइलर केवल सूचक के ऑफसेट भाग की तुलना करने का हकदार होगा, न कि खंड का हिस्सा।)

हम्म। मैं कोशिश करूंगा और कुछ और सोचूंगा।

संपादित करें: उत्कृष्ट C FAQ में कुछ स्पष्ट लिंक जोड़े गए।


2
संयोग से, कुछ समय पहले मैंने क्लू ( cluecc.sourceforge.net ) नामक एक प्रायोगिक परियोजना की थी, जिसने आपको C को Lua, जावास्क्रिप्ट, पर्ल, LISP, आदि में संकलित करने की अनुमति दी थी। इसने बिंदुओं को काम करने के लिए C मानक में अपरिभाषित व्यवहार का बेरहमी से शोषण किया। । इस पर इस परीक्षण का प्रयास करना दिलचस्प हो सकता है।
डेविड

1
IIRC C आपको एक ऑब्जेक्ट के अंत से परे 1 द्वारा एक संकेतक बढ़ाने की अनुमति देता है , लेकिन आगे नहीं। हालाँकि, किसी वस्तु की शुरुआत से पहले उसे किसी स्थिति में घटाना अनुमत नहीं है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

@R। सी ++ में भी। और आगे बढ़ने पर टूट सकता है अगर पॉइंटर को बढ़ाने से सीपीयू पर एक अतिप्रवाह का कारण बनता है, जो पूर्णांकों के लिए केवल संकेत नहीं मानते हैं।
जुल्फ

5

मुझे लगता है कि आपको "गलत" मान्यताओं के दो बहुत अलग वर्गों के बीच अंतर करने का प्रयास करना चाहिए। एक अच्छा आधा (सही बदलाव और साइन एक्सटेंशन, एएससीआईआई-संगत एन्कोडिंग, मेमोरी रैखिक है, डेटा और फ़ंक्शन पॉइंटर्स संगत हैं, आदि) अधिकांश के लिए बहुत ही उचित धारणाएं हैं सी कोडर बनाने के हैं, और मानक के हिस्से के रूप में भी शामिल हो सकते हैं। अगर C को आज डिजाइन किया जा रहा था और अगर हमारे पास विरासत आईबीएम कबाड़ दादा-दादी नहीं थी। अन्य आधी (मेमोरी एलियासिंग से संबंधित चीजें, लाइब्रेरी के कार्य जब इनपुट और आउटपुट मेमोरी ओवरलैप होते हैं, तो उस बिंदु की तरह 32-बिट धारणाएं फिट होती हैं intया जिसमें आप उपयोग कर सकते हैंmalloc एक प्रोटोटाइप के बिना, कि कन्वेंशन को कॉल करना वैरिएडिक और नॉन-वैरेडिक फ़ंक्शंस के लिए समान है, ...) या तो अनुकूलन के साथ संघर्ष आधुनिक संकलक प्रदर्शन करना चाहते हैं या 64-बिट मशीनों या अन्य नई तकनीक के लिए माइग्रेशन के साथ।


यह सिर्फ "आईबीएम कबाड़" नहीं है (हालांकि मैं सहमत हूं कि आईबीएम सामान रद्दी है)। कई एम्बेडेड सिस्टम में आज समान समस्याएं हैं।
rmeador

स्पष्ट करने के लिए, mallocबिना प्रोटोटाइप का उपयोग करने का मतलब नहीं है <stdlib.h>, जिसमें mallocडिफ़ॉल्ट रूप से कारण होता है int malloc(int), यदि आप 64-बिट का समर्थन करना चाहते हैं तो कोई भी नहीं।
जॉय एडम्स

तकनीकी रूप से आप स्वतंत्र हैं <stdlib.h>जब तक कि आप एक और हेडर शामिल नहीं करते हैं जो परिभाषित करता है size_tऔर तब आप mallocअपने आप को एक सही प्रोटोटाइप के साथ घोषित करते हैं।
आर .. गिटहब स्टॉप हेल्पिंग ICE

5

यहाँ एक मजेदार है: इस समारोह में क्या गलत है?

float sum(unsigned int n, ...)
{
    float v = 0;
    va_list ap;
    va_start(ap, n);
    while (n--)
        v += va_arg(ap, float);
    va_end(ap);
    return v;
}

[उत्तर (रोट 13): इनव्नक्विप नेथज़्रगफ बोरल गुर ब्यक् एक्स एंड ई सेबग्वबा एहिर्फ, जुव्पु ज़र्नाफ एलब पनाबग हफ़्फ़ 'सिब्न्ग' ('प्यून' बी 'फबग' हो) वीए in_net! नक गूर pbzcvyre vf erdhverq abg gb gerng guvf nf n pbzcvyr-gvzr reebe। (टीपीपी क़ब्र rzvg n jneavat, gubhtu।)


ओह, यह एक अच्छा है। क्लेंग 2.7 इसे खाता है और बिना किसी चेतावनी के पूरा बकवास पैदा करता है।
नॉर्डिक मेनफ्रेम

va_arg फैलता है अगर यह एक मैक्रो है और जबकि लूप केवल पहले बयान को निष्पादित करता है, शायद बहुत से?
मैस्टर

नहींं (यदि ऐसा हुआ तो यह कार्यान्वयन में एक बग होगा)।
zwol

5
EXPECT("## pow() gives exact results for integer arguments", pow(2, 4) == 16);

एक अन्य पाठ मोड के बारे में है fopen। अधिकांश प्रोग्रामर यह मानते हैं कि या तो टेक्स्ट और बाइनरी एक ही हैं (यूनिक्स) या फिर टेक्स्ट मोड \rअक्षर (विंडोज) जोड़ता है । लेकिन C को उन प्रणालियों में पोर्ट किया गया है जो निश्चित-चौड़ाई के रिकॉर्ड का उपयोग करते हैं, जिस fputc('\n', file)पर एक पाठ फ़ाइल का मतलब रिक्त स्थान या कुछ जोड़ना है जब तक कि फ़ाइल का आकार रिकॉर्ड लंबाई का एक बहु नहीं हो।

और यहाँ मेरे परिणाम हैं:

g86 (Ubuntu 4.4.3-4ubuntu5) 4.4.3 x86-64 पर

We like to think that:
..05 int has the size of pointers
   but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..14 i++ is strictly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
   but 'sizeof(size_t)==sizeof(unsigned int)' is false.
From what I can say with my puny test cases, you are 78% mainstream

मैंने वास्तव में कोड देखा है जो pow(2, n)बिट संचालन के साथ संयुक्त है ।
dan04

4

उनमें से कुछ को आसानी से सी के अंदर से परीक्षण नहीं किया जा सकता है क्योंकि कार्यक्रम कार्यान्वयन पर क्रैश होने की संभावना है जहां धारणा पकड़ में नहीं आती है।


"सूचक-मूल्यवान चर के साथ कुछ भी करना ठीक है। यदि आपको इसे प्रतिबंधित करना है तो केवल एक वैध सूचक मान होना चाहिए।"

void noop(void *p); /* A no-op function that the compiler doesn't know to optimize away */
int main () {
    char *p = malloc(1);
    free(p);
    noop(p); /* may crash in implementations that verify pointer accesses */
    noop(p - 42000); /* and if not the previous instruction, maybe this one */
}

अभिन्न और फ़्लोटिंग पॉइंट प्रकार (के अलावा unsigned char) के साथ ही, जिन्हें ट्रैप प्रतिनिधित्व करने की अनुमति है।


"पूर्णांक गणना चारों ओर लपेटती है। इसलिए यह कार्यक्रम एक बड़े नकारात्मक पूर्णांक को प्रिंट करता है।"

#include <stdio.h>
int main () {
    printf("%d\n", INT_MAX+1); /* may crash due to signed integer overflow */
    return 0;
}

(केवल C89) "के अंत में गिरना ठीक है main।"

#include <stdio.h>
int main () {
    puts("Hello.");
} /* The status code is 7 on many implementations. */

2
एक ठोस उदाहरण के रूप में: जब संकलित किया जाता है gcc -ftrapv -O, तो आउटपुट का We like to think that:पालन ​​किया जाता हैAborted
कैफे

@ कफ: "यह विकल्प अतिरिक्त, घटाव, गुणन कार्यों पर हस्ताक्षरित अतिप्रवाह के लिए जाल बनाता है।" जानकर अच्छा लगा, धन्यवाद।
गिलेस एसओ- बुराई को रोकना '

1
अंतिम सी + + (98, 03 और 0x) के रूप में अच्छी तरह से ठीक है, और अंतर्निहित रिटर्न 0.
जुल्फ

जो बुरा है क्योंकि पूर्व-एएनएसआई सी ने इसकी अनुमति दी थी और सी 99 भी करता है।
जोशुआ

@ जोशुआ: AFAIK पूर्व-एएनएसआई सी और C89 के बीच कोई अंतर नहीं के mainसाथ वापसी पर कोई अंतर नहीं है: कार्यक्रम सही है लेकिन एक अपरिभाषित समाप्ति स्थिति (C89 §2.1.2.2) देता है। कई कार्यान्वयन के साथ (जैसे कि जीसीसी, और पुराने यूनिक्स कंपाइलर) आपको उस बिंदु पर एक निश्चित रजिस्टर में जो कुछ भी था। प्रोग्राम आम तौर पर तब तक काम करता है जब तक कि इसे मेकफाइल या अन्य वातावरण में उपयोग नहीं किया जाता है जो समाप्ति की स्थिति की जांच करता है।
गिल्स एसओ- बुराई को रोकना '

4

अच्छी तरह से अभी तक क्लासिक पोर्टेबिलिटी मान्यताओं का अनुमान नहीं है

  • अभिन्न प्रकार के आकार के बारे में धारणाएं
  • endianness

4
"एंडियननेस", जिसमें "एक एंडियननेस शामिल है": मध्य-एंडियन मशीनें हैं, और मानक shortदो बाइट्स 24248 और fdb97531 के रूप में एक मूल्य फेडकैब 9876543210 (कि 16 बाइनरी अंक) को संग्रहीत करने जैसी अजीब चीजों की अनुमति देता है ।
गिल्स एसओ- बुराई को रोकना '

हाँ धीरज रखने के लिए सुनिश्चित है कि मिश्रित / मध्य अंतियन के साथ-साथ बड़े और छोटे भी शामिल हैं। यदि आप कस्टम हार्डवेयर पर जाते हैं, तो आपके पास किसी भी बस में कोई भी एंडियनस हो सकता है।
जे.के.

मध्य एंडियन को पीडीपी एंडियन के रूप में जाना जाता है। गिलेश कुछ भी निराला भले ही टीसीपी / आईपी को लागू करने के लिए सिरदर्द का कारण बनता है।
जोशुआ

@ गिल्स: मिडिल-एंडियन ... मुझे बहुत खुशी है कि मैं उस पर विकास नहीं कर रहा हूं। (लेकिन अब मैं एक मिडिल-एंडियन नेटवर्किंग प्रोजेक्ट करने के लिए कहूँगा, मुझे यकीन है ...)
पॉल नाथन

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

4
  • फ्लोटिंग पॉइंट प्रतिनिधित्व के कारण विवेकाधीन त्रुटियां। उदाहरण के लिए, यदि आप द्विघात समीकरणों को हल करने के लिए मानक सूत्र का उपयोग करते हैं, या लगभग अंतर को परिमित करने के लिए अंतर, या भिन्नताओं की गणना करने के लिए मानक सूत्र का उपयोग करते हैं, तो सटीक संख्याओं के बीच अंतर की गणना के कारण परिशुद्धता खो जाएगी। रैखिक प्रणालियों को हल करने के लिए Gauing एल्गोरिथ्म खराब है क्योंकि गोलाई त्रुटियां जमा होती हैं, इस प्रकार एक क्यूआर या एलयू अपघटन, चोल्स्की अपघटन, एसवीडी, आदि का उपयोग करता है। अस्थायी बिंदु संख्याओं का जोड़ सहयोगी नहीं है। अस्वाभाविक, अनंत और NaN मान हैं। + बी -

  • स्ट्रिंग्स: वर्णों, कोड बिंदुओं और कोड इकाइयों के बीच अंतर। विभिन्न ऑपरेटिंग सिस्टम पर यूनिकोड कैसे लागू किया जाता है; यूनिकोड एनकोडिंग्स। एक यूनिकोड फ़ाइल नाम के साथ एक फ़ाइल खोलना पोर्टेबल तरीके से C ++ के साथ संभव नहीं है।

  • दौड़ की स्थिति, यहां तक ​​कि बिना थ्रेडिंग के: यदि आप परीक्षण करते हैं कि क्या कोई फ़ाइल मौजूद है, तो परिणाम किसी भी समय अमान्य हो सकता है।

  • ERROR_SUCCESS = 0


4

पूर्णांक आकारों के लिए एक चेक शामिल करें। ज्यादातर लोग यह मानते हैं कि एक इंट शॉर्ट से बड़ा है, एक चार से बड़ा है। हालाँकि, ये सभी झूठे हो सकते हैं:sizeof(char) < sizeof(int); sizeof(short) < sizeof(int); sizeof(char) < sizeof(short)

यह कोड विफल हो सकता है (असम्बद्ध पहुंच के लिए क्रैश)

unsigned char buf[64];

int i = 234;
int *p = &buf[1];
*p = i;
i = *p;

क्या यह कोड C ++ में विफल होगा? IIRC, यह असंबंधित प्रकारों के बीच संकेत देने के लिए अवैध है, चार * के लिए EXCEPT, जो किसी भी प्रकार के लिए डाली जा सकती है (या क्या यह दूसरा तरीका है?)।
rmeador

1
आप सिर्फ int *p = (int*)&buf[1];सी ++ में कर सकते हैं, लोगों को उम्मीद है कि काम भी करना होगा।
nos

@nos, हाँ, जो विफल हो सकता है, लेकिन असफलता दुर्घटना है इसलिए उसका कार्यक्रम उस एक के लिए परीक्षण नहीं कर सकता। :(
जोशुआ

1
sizeof(char) < sizeof(int)आवश्यक है। उदाहरण के लिए, fgetc () चरित्र के मान को एक अहस्ताक्षरित चार के रूप में इंट में परिवर्तित कर EOFदेता है , या जो एक नकारात्मक मूल्य है। unsigned charपैडिंग बिट्स नहीं हो सकते हैं, इसलिए ऐसा करने का एकमात्र तरीका है कि इंट को चार से बड़ा बना दिया जाए। इसके अलावा, सी के अधिकांश संस्करणों में सी -32 की आवश्यकता है कि -32767..32767 से किसी भी मूल्य को एक इंट में संग्रहीत किया जा सकता है।
जिल

@ फिर भी, वहाँ 32 बिट chars और 32 बिट ints के साथ DSPs है।
nos

3

अंतर्निहित डेटा प्रकारों के बारे में कुछ बातें:

  • charऔर signed charवास्तव में दो अलग-अलग प्रकार के होते हैं (विपरीत intऔर signed intजो एक ही हस्ताक्षरित पूर्णांक प्रकार को संदर्भित करते हैं)।
  • हस्ताक्षर किए गए पूर्णांकों को दो के पूरक का उपयोग करने की आवश्यकता नहीं है। ओनेस के पूरक और संकेत + परिमाण भी नकारात्मक संख्याओं के मान्य प्रतिनिधित्व हैं। यह नकारात्मक संचालनों को परिभाषित करने वाले बिट संचालन को परिभाषित करता है
  • यदि आप साइन-इन पूर्णांक चर के लिए एक आउट-ऑफ-रेंज सीमा पूर्णांक असाइन करते हैं, तो व्यवहार कार्यान्वयन-परिभाषित होता है
  • C90 में, -3/5वापस आ सकता है 0या -1। एक ऑपरेंड नकारात्मक होने की स्थिति में शून्य की ओर बढ़ना केवल C99 में ऊपर की ओर और C ++ 0x के ऊपर की गारंटी है।
  • अंतर्निहित प्रकारों के लिए कोई सटीक आकार की गारंटी नहीं है। मानक केवल न्यूनतम आवश्यकताओं को एक तरह के रूप में शामिल किया गया intहै कम से कम 16 बिट, एक longहै कम से कम 32 बिट, एकlong long है कम से कम 64 बिट्स। A floatकम से कम 6 सबसे महत्वपूर्ण दशमलव अंकों का सही प्रतिनिधित्व कर सकता है। एdouble कम से कम 10 सबसे महत्वपूर्ण दशमलव अंकों का सही प्रतिनिधित्व कर सकता है।
  • अस्थायी बिंदु संख्याओं का प्रतिनिधित्व करने के लिए IEEE 754 अनिवार्य नहीं है।

बेशक, अधिकांश मशीनों पर हमारे पास दो पूरक और IEEE 754 फ़्लोट होंगे।


मुझे आश्चर्य है कि पूर्व-निर्धारित पूर्णांक के बजाय पूर्णांक पूर्णांक असाइनमेंट को लागू करने में क्या मूल्य है? कुछ प्लेटफार्मों पर, इस तरह की आवश्यकता कंपाइलर के लिए अतिरिक्त कोड उत्पन्न करने के लिए मजबूर करेगी int mult(int a,int b) { return (long)a*b;}[जैसे कि अगर int32 बिट्स हैं, लेकिन रजिस्टर और long64 हैं]। ऐसी आवश्यकता के बिना, सबसे तेज़ कार्यान्वयन का "प्राकृतिक" व्यवहार समान long l=mult(1000000,1000000);होगा , भले ही वह "असंभव" मूल्य हो । l1000000000000int
सुपरकैट

3

इसके बारे में क्या खयाल है:

कोई डेटा पॉइंटर कभी भी एक वैध फ़ंक्शन पॉइंटर के समान नहीं हो सकता है।

यह सभी सपाट मॉडल, MS-DOS टिनि, लार्ज और बड़ी मॉडल के लिए TRUE है, MS-DOS SMALL मॉडल के लिए गलत है, और लगभग हमेशा MEDIUM और COMPACT मॉडल के लिए गलत है (लोड पते पर निर्भर करता है, आपको वास्तव में पुराने डॉस की आवश्यकता होगी इसे सच करो)।

मैं इसके लिए कोई टेस्ट नहीं लिख सकता

और बदतर: ptrdiff_t के लिए डाले गए बिंदुओं की तुलना की जा सकती है। यह MS-DOS LARGE मॉडल के लिए सही नहीं है (LARGE और HUGE के बीच का एकमात्र अंतर है बड़ा होता है पॉइंटर्स को सामान्य करने के लिए कंपाइलर कोड)।

मैं एक परीक्षण नहीं लिख सकता क्योंकि पर्यावरण जहां यह बम मुश्किल से 64K से अधिक एक बफर आवंटित नहीं करेगा, इसलिए यह प्रदर्शित करता है कि कोड अन्य प्लेटफार्मों पर दुर्घटनाग्रस्त हो जाएगा।

यह विशेष परीक्षण अब एक-दोषपूर्ण प्रणाली पर पारित होगा (ध्यान दें कि यह मॉलॉक के आंतरिक पर निर्भर करता है):

  char *ptr1 = malloc(16);
  char *ptr2 = malloc(16);
  if ((ptrdiff_t)ptr2 - 0x20000 == (ptrdiff_t)ptr1)
      printf("We like to think that unrelated pointers are equality comparable when cast to the appropriate integer, but they're not.");

3

संपादित करें: कार्यक्रम के अंतिम संस्करण के लिए अपडेट किया गया

सोलारिस-स्पार्क

32 बिट में 3.4.6

We like to think that:
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
   but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 72% mainstream

64 बिट में 3.4.6 g

We like to think that:
..05 int has the size of pointers
   but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09 overshifting is *always* okay
   but '(1<<BITS_PER_INT)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
   but 'sizeof(size_t)==sizeof(unsigned int)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 68% mainstream

और SUNStudio 11 32 बिट के साथ

We like to think that:
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
From what I can say with my puny test cases, you are 79% mainstream

और SUNStudio 11 64 बिट के साथ

We like to think that:
..05 int has the size of pointers
   but 'sizeof(int)==sizeof(void*)' is false.
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits always come first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is strictly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..17 size_t is unsigned int
   but 'sizeof(size_t)==sizeof(unsigned int)' is false.
From what I can say with my puny test cases, you are 75% mainstream

2

आप पाठ-मोड का उपयोग कर सकते हैं (fopen("filename", "r") किसी भी प्रकार की पाठ फ़ाइल को पढ़ने के ) का ।

जबकि यह सिद्धांत में ठीक काम करना चाहिए , यदि आप ftell()अपने कोड में भी उपयोग करते हैं, और आपकी पाठ फ़ाइल में UNIX- शैली लाइन-एंडिंग्स हैं, तो विंडोज मानक पुस्तकालय के कुछ संस्करणों में, ftell()अक्सर अमान्य मान वापस आ जाएंगे। इसका समाधान बाइनरी मोड का उपयोग करना है ( fopen("filename", "rb"))।


1

AIX 5.3 पर gcc 3.3.2 (हाँ, हमें gcc अपडेट करने की आवश्यकता है)

We like to think that:
..04 a char is signed
   but 'CHAR_MIN==SCHAR_MIN' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..13 The smallest bits come always first
   but '(t=0x1234,0x34==*(char*)&t)' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..16 malloc()=NULL means out of memory
   but '(malloc(0)!=NULL)' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 71% mainstream

1

एक धारणा जो C ++ में कुछ कर सकती है, structवह यह है कि सी। में क्या किया जा सकता है, इस तक सीमित है। तथ्य यह है कि, C ++ में, a structजैसा हैclass यह अपवाद की कि इसमें डिफ़ॉल्ट रूप से सब कुछ सार्वजनिक है।

सी ++ संरचना:

struct Foo
{
  int number1_;  //this is public by default


//this is valid in C++:    
private: 
  void Testing1();
  int number2_;

protected:
  void Testing2();
};

1

विभिन्न प्रणालियों पर मानक गणित कार्य समान परिणाम नहीं देते हैं।


1

विज़ुअल स्टूडियो एक्सप्रेस 2010 32-बिट x86 पर।

Z:\sandbox>cl testtoy.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

testtoy.c
testtoy.c(54) : warning C4293: '<<' : shift count negative or too big, undefined
 behavior
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:testtoy.exe
testtoy.obj

Z:\sandbox>testtoy.exe
We like to think that:
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..09a minus shifts backwards
   but '(t=-1,(15<<t)==7)' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
..22 floating point is always IEEE
   but 'STDC_IEC_559_is_defined' is false.
From what I can say with my puny test cases, you are 78% mainstream

1

Via Codepad.org (C++: g++ 4.1.2 flags: -O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch । )।

ध्यान दें कि कोडपैड के पास नहीं था stddef.h। मैंने चेतावनियों को त्रुटियों के रूप में उपयोग करते हुए कोड 9 को हटा दिया। मैंने countचर का नाम भी बदल दिया क्योंकि यह पहले से ही किसी कारण से परिभाषित किया गया था।

We like to think that:
..08 overshifting is okay
   but '(1<<bits_per_int)==0' is false.
..14 i++ is structly left to right
   but '(i=0,a[i++]=i,a[0]==1)' is false.
..15 structs are packed
   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false.
..19-3 int<long
   but 'sizeof(int)<sizeof(long)' is false.
From what I can say with my puny test cases, you are 84% mainstream

1

कैसे अत्यधिक मात्रा में राइट-शिफ्टिंग के बारे में - क्या यह मानक द्वारा अनुमत है, या परीक्षण के लायक है?

क्या मानक C निम्नलिखित कार्यक्रम के व्यवहार को निर्दिष्ट करता है:

शून्य प्रिंट_स्ट्रिंग (चार * सेंट)
{
  char ch;
  जबकि (ch = * st ++)! = 0)
    putch (ch); / * मान लें कि यह परिभाषित है * /
}
इंट मेन (शून्य)
{
  print_string ( "हैलो");
  वापसी 0;
}

कम से कम एक कंपाइलर का मैं उपयोग करता हूं, वह कोड तब तक विफल रहेगा जब तक कि print_string का तर्क "char const *" नहीं है। क्या मानक इस तरह के प्रतिबंध की अनुमति देता है?

कुछ प्रणालियाँ किसी को अप्रभावित 'int' की ओर संकेत करती हैं और अन्य नहीं। परीक्षण के लायक हो सकता है।


C89 the3.3.7: "यदि सही ऑपरेंड का मान ऋणात्मक है या प्रोमोटेड लेफ्ट ऑपरेंड के बिट्स में चौड़ाई के बराबर या उससे अधिक है, तो व्यवहार अपरिभाषित है।" (दोनों पर लागू होता है ) <<और >>। C99 की समान भाषा in6.5.7-3 में है।
गिल्स एसओ- बुराई को रोकना '

इसके अलावा putch(आपने मानक का उपयोग क्यों नहीं किया putchar?), मैं आपके कार्यक्रम में कोई अपरिभाषित व्यवहार नहीं देख सकता। C89 string3.1.4 निर्दिष्ट करता है कि "एक चरित्र स्ट्रिंग शाब्दिक है [...] प्रकार 'चार का सरणी'" (नोट: नहीं const), और कहा कि "अगर कार्यक्रम एक स्ट्रिंग शाब्दिक [...] को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।" । संकलक क्या है, और यह इस कार्यक्रम का अनुवाद कैसे करता है?
गिल्स एसओ- बुराई को रोकना '

2
C ++ वर्ण में स्थिरांक char [] नहीं हैं , वे const char [] हैं। हालांकि ... वहाँ इस्तेमाल किया आप एक संदर्भ में, जहां एक चार * की उम्मीद थी और एक प्रकार की त्रुटि नहीं मिल में एक स्ट्रिंग निरंतर उपयोग करने के लिए अनुमति देने के लिए प्रकार प्रणाली में एक विशिष्ट छेद किया जाना है। इससे ऐसी परिस्थितियाँ पैदा हुईं जहाँ Print_string ("foo") काम करेगा लेकिन print_string ("foo" +0) नहीं होगा। यह गहराई से भ्रमित करने वाला था, विशेष रूप से ऐसे वातावरण में जहाँ C फाइलें डिफ़ॉल्ट रूप से C ++ कंपाइलर का उपयोग करके संकलित की जाती हैं। नए संकलकों में छेद को हटा दिया गया है, लेकिन अभी भी बहुत सारे पुराने हैं। AFAIK C99 अभी भी स्ट्रिंग स्थिरांक को परिभाषित करता है []।
डेविड

1
नियंत्रकों के माइक्रोचिप पीआईसी श्रृंखला के लिए हाईटेक संकलक पर, भंडारण क्वालीफायर के बिना एक सूचक केवल रैम को इंगित कर सकता है। एक कास्ट-योग्य पॉइंटर रैम या रोम को इंगित कर सकता है। गैर-कांस्टेबल-योग्य पॉइंटर्स को सीधे कोड में संदर्भित किया जाता है; कांस्टेबल-क्वालिफाइड पॉइंटर्स को लाइब्रेरी रूटीन के माध्यम से डिरेल किया जाता है। विशेष प्रकार के PIC के आधार पर, गैर-कांस्टेबल-योग्य पॉइंटर्स 1 या 2 बाइट्स हैं; कॉन्स्ट-योग्य लोग 2 या 3 हैं। चूंकि ROM रैम से बहुत अधिक भरपूर है, इसलिए रोम में स्थिरांक होना एक अच्छी बात है।
सुपरकैट

@ दी गई जानकारी: मेरी पिछली टिप्पणी पर भी ध्यान दें। मैं ऐसे कंपाइलरों को प्राथमिकता देता हूं जो हार्डवेयर स्टोरेज क्लास को दर्शाने के लिए "const" के अलावा क्वालीफायर का उपयोग करते हैं; हाईटेक कंपाइलर की स्टोरेज क्लास एलोकेशन (उदाहरण के लिए डेटा आइटम्स जिनके "कंपोनेंट साइज़" एक बाइट या 256 बाइट्स से अधिक होते हैं, जो "बिग" सेगमेंट में जाते हैं, "डेटा" में चले जाते हैं) bss "खंड वे परिभाषित किए गए मॉड्यूल के लिए, सभी मॉड्यूल में" bss "आइटम 256 बाइट्स के भीतर फिट होने चाहिए। 256 बाइट्स से थोड़ा कम होने वाली
सारणियाँ

0

FYI करें, उन लोगों के लिए जिन्हें अपने C कौशलों का जावा में अनुवाद करना है, यहाँ कुछ गोचर हैं।

EXPECT("03 a char is 8 bits",CHAR_BIT==8);
EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);

जावा में, चार्ट 16-बिट और हस्ताक्षरित है। बाइट 8-बिट और हस्ताक्षरित है।

/* not true for Windows-64 */
EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));

लंबी हमेशा 64-बिट होती है, संदर्भ 32-बिट या 64-बिट हो सकते हैं (यदि आपके पास 32 जीबी से अधिक ऐप है) 64-बिट जेवीएम आमतौर पर 32-बिट संदर्भ का उपयोग करते हैं।

EXPECT("08 overshifting is okay",(1<<bits_per_int)==0);
EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);

शिफ्ट को मास्क किया जाता है ताकि i << 64 == i == i << -64, i << 63 == i << -1

EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));

ByteOrder.nativeOrder () BIG_ENDIAN या LITTLE_ENDIAN हो सकता है

EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));

i = i++ कभी नही बदलता है i

/* suggested by David Thornley */
EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));

संग्रह और सरणियों का आकार हमेशा 32-बिट होता है चाहे जेवीएम 32-बिट हो या 64-बिट।

EXPECT("19-1 char<short",sizeof(char)<sizeof(short));
EXPECT("19-2 short<int",sizeof(short)<sizeof(int));
EXPECT("19-3 int<long",sizeof(int)<sizeof(long));

char 16-बिट है, शॉर्ट 16-बिट है, इंट 32-बिट है और लॉन्ग 64-बिट है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.