itsource

C/C++에서 사람들이 하는 부당한 가정을 설명하기 위한 교육 도구에는 무엇이 있습니까?

mycopycode 2022. 8. 31. 22:51
반응형

C/C++에서 사람들이 하는 부당한 가정을 설명하기 위한 교육 도구에는 무엇이 있습니까?

초보자(및 중급자) 프로그래머가 C, C++ 및 그 플랫폼에서 보증되지 않은 가정을 인식하고 도전할 수 있도록 SO를 위한 작은 교육 도구를 준비하려고 합니다.

예:

  • "주변으로 싸매기"
  • "모두가 ASCII를 가지고 있다"
  • "기능 포인터를 보이드에 저장할 수 있습니다*"

소규모 테스트 프로그램을 다양한 플랫폼에서 실행할 수 있다고 생각했습니다.그것은, SO에 관한 경험으로부터, 많은 경험이 없는/반경험의 주류 개발자에 의해서 행해지는 「실현 가능한」전제를 실행해, 다양한 머신에서 어떻게 망가지는지를 기록합니다.

이 작업의 목적은 무엇인가를 하는 것이 '안전하다'는 것을 증명하는 것이 아니라(그것은 불가능하지만 테스트는 그것이 깨졌을 경우에만 증명한다), 가장 눈에 띄지 않는 표현이 정의되지 않은 동작 또는 구현 정의된 동작을 가지고 있는 경우 다른 기계에서 어떻게 깨지는지를 가장 불편하지 않은 개인에게도 증명하는 것입니다.

이를 위해 저는 당신에게 묻고 싶습니다.

  • 어떻게 하면 이 아이디어를 개선할 수 있을까요?
  • 어떤 테스트가 좋을까? 어떻게 보여야 할까?
  • 사용할 수 있는 플랫폼에서 테스트를 수행하고 결과를 게시하여 플랫폼 데이터베이스, 플랫폼 간의 차이, 이 차이가 허용되는 이유를 파악할 수 있도록 해 주시겠습니까?

테스트 완구의 최신 버전은 다음과 같습니다.

#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 repo를 작성했습니다.파일은 "gotcha" 입니다.c":

여기에서 설명하거나 명확히 할 수 있도록 패치 또는 새로운 아이디어를 사용하여 답변해 주십시오.그럼 그것들을 gotcha.c로 통합하겠습니다.

다음을 포함한 하위 표현의 평가 순서

  • 함수 호출의 인수와
  • "연산자")+,-,=,*,/),,, 음음음음음음음:
    • 논리 연산자이진 연산자)&& ★★★★★★★★★★★★★★★★★」||
    • 연산자삼원 조건 연산자)?:및 , 。
    • 연산자쉼표 연산자),)

미지정

예를들면

  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;
  } 

하다를 요.++ ★★★★★★★★★★★★★★★★★」--츠요시

a[i++]= i;

예를 들어, 는 구문적으로는 합법적이지만 추론해야 할 많은 사항에 따라 다양한 결과를 생성합니다.

를 가진 의 스테이트먼트++ (오류)--여러 번 발생하는 변수가 문제가 됩니다.

오래전에, 나는 C를 가르치고 있었다. 교과서에서 C를 가르쳤다.

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

예시 질문으로.학생에게 실패한 이유는sizeof는 타입의 합니다.size_t 아니라, 이에요.int,int에서는, 비트와 「16」이 되고 있습니다.size_t 인치 (은 680 x 0 (Macintosh 680x0 광속 C 습 ( ( ( ( ( ( 。★★★★★★★★★★★★★★★★★★★★★★★」


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

printf가 크래쉬 합니다."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

clang 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

intel 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

Turbo C++/DOS/소형 메모리

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

Turbo C++/DOS/중간 메모리

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

Turbo C++/DOS/컴팩트 메모리

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@Commodore PET(부 에뮬레이터)

alt 텍스트


나중에 업데이트하겠습니다.


Windows XP에서의 Borland C++ Builder 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

Visual Studio Express 2010 C++ CLR, Windows 7 64비트

(CLR 컴파일러는 순수 C를 지원하지 않으므로 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

는, 의 Windows 의 LLP64 를 사용합니다. 다.int ★★★★★★★★★★★★★★★★★」long는 32비트로 정의되어 있습니다.즉, 어느 쪽도 포인터에 충분히 길지 않습니다.


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비트 PC가 있지만 코드와 데이터는 별도의 주소 공간에 있습니다.더 큰 Atmegas는 22비트 PC를 가지고 있습니다!


MacOSX 10.6의 gcc 4.2.1, -arch ppc로 컴파일

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

여기 재미있는 것이 있습니다.이 기능에 무슨 문제가 있나요?

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;
}

[정답(rot13):필연적인 nethzragf borl gur byq X&E cebzbgvba ehyrf, juvpu zrnaf lbh pnaabg hfr hfr 'sybng'('be 'fubeg'가 되다) va in_net!Naq gur pbzcvyre vf erdhverq abg gb gerng guvf nf pbzcvyr-gvzr reebe.(TPP qbrf rzvg n jneavat, gubhtu)

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

는 '텍스트 에 대한 내용입니다.fopen가 'Unix'(Unix), 'Unix'(Unix), 'Unix'를 \r[캐릭터], 레코드를 사용하는 이에서는 ", C"가 사용됩니다.fputc('\n', file)텍스트 파일에서는 파일 크기가 레코드 길이의 배수가 될 때까지 공백 등을 추가하는 것을 의미합니다.

결과는 다음과 같습니다.

gcc(Ubuntu 4.4.3-4ubuntu5) x86-64의 경우 4.4.3

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

그 중 일부는 C 내부에서 쉽게 테스트할 수 없습니다.왜냐하면 이 프로그램은 가정이 유지되지 않는 구현에서 충돌할 가능성이 높기 때문입니다.


"포인터 값 변수를 사용하여 어떤 작업도 수행할 수 있습니다.참조 해제 시 유효한 포인터 값만 포함하면 됩니다."

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. */

정수 크기 검사를 포함합니다.짧다 이 수 : 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.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;

이건 어때?

어떤 데이터 포인터도 유효한 함수 포인터와 같을 수 없습니다.

이것은 모든 플랫 모델, MS-DOS TINY, LARGE 및 HUGE 모델, MS-DOS SMARG 모델, MEDIUM 및 COMPT 모델에서는 거의 항상 false입니다(로드 주소에 따라 다릅니다.이것을 실현하려면 매우 오래된 DOS가 필요합니다).

나는 이것에 대한 시험을 쓸 수 없다.

더 나쁜 것은 ptrdiff_t에 캐스트된 포인터가 비교될 수 있다는 것입니다.MS-DOS LARGE 모델에서는 그렇지 않습니다(LARGE와 HUGE의 유일한 차이점은 포인터를 정규화하기 위해 컴파일러 코드를 추가하는 것입니다).

이 폭탄이 터지는 환경은 64K 이상의 버퍼를 할당하지 않기 때문에 테스트를 작성할 수 없습니다.따라서 이를 증명하는 코드가 다른 플랫폼에서 크래시됩니다.

이 특정 테스트는 현재 사용되지 않는 하나의 시스템으로 통과됩니다(malloc의 내부에 따라 달라집니다).

  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.");

매우 흥미롭지요!

기타 체크할 수 있는 사항은 다음과 같습니다.

  • 함수 포인터와 데이터 포인터가 동일한 주소 공간에 존재합니까? (DOS 스몰 모드와 같은 하버드 아키텍처 머신에서의 브레이크)하지만 어떻게 테스트해야 할지 모르겠습니다.)

  • NULL 데이터 포인터를 적절한 정수 타입으로 캐스팅하면 숫자 값 0이 됩니까? (몇몇 오래된 머신에서는 브레이크가 발생합니다 --- http://c-faq.com/null/machexamp.html.) 참조.함수 포인터도 마찬가지입니다.또한 값이 다를 수 있습니다.

  • 대응하는 스토리지 오브젝트의 끝을 지나 포인터를 증가시키고 나서 다시 되돌리면, 적절한 결과를 얻을 수 있습니까?(실제로 기동하는 머신은 모릅니다만, C사양에서는 (a) 어레이의 내용이나 (b) arr 직후의 요소를 가리키지 않는 포인터는 생각할 수 없다고 생각합니다.ray 또는 (c) NULL. http://c-faq.com/aryptr/non0based.html.) 참조

  • < 및 >와 다른 스토리지 오브젝트에 대한 2개의 포인터를 비교하면 일관된 결과를 얻을 수 있습니까?(이러한 세그먼트 베이스의 머신에서는, 이러한 파손을 상상할 수 있습니다.스펙에서는 이러한 비교는 금지되어 있기 때문에, 컴파일러는 포인터의 오프셋 부분만을 비교할 수 있고 세그먼트 부분은 비교할 수 없습니다.)

음, 좀 더 생각해 볼게요

편집: 우수한 C FAQ에 대한 명확한 링크를 추가했습니다.

저는 여러분이 "잘못된" 두 가지 매우 다른 종류의 가정을 구별하기 위해 노력해야 한다고 생각합니다.적절한 절반(오른쪽 시프트 및 부호 확장자, ASCII 호환 인코딩, 메모리는 선형, 데이터와 함수 포인터 호환성 등)은 대부분의 C 코더가 만들기에 합리적인 가정이며, C가 현재 설계되고 있고 레거시 IBM 정크 포터가 없다면 표준의 일부로 포함될 수도 있습니다.나머지 절반(메모리 에일리어싱에 관한 것, 입출력 메모리가 오버랩되었을 때의 라이브러리 기능 동작, 포인터와 같은 32비트의 전제 조건)int '사용할 수 있습니다'를 사용할 수 .malloc시제품이 없으면 호출 규칙은 가변 및 비변동 함수와 동일합니다. ...) 최신 컴파일러가 실행하는 최적화와 충돌하거나 64비트 머신으로의 이행 또는 기타 신기술과 충돌합니다.

아직 의도되지 않은 전형적인 휴대성 전제 조건은 다음과 같습니다.

  • 적분형 크기에 관한 가정
  • 엔디안성
  • 부동소수점 표현으로 인한 Discretization 오류입니다.예를 들어, 표준 공식을 사용하여 2차 방정식을 풀거나, 근사 도함수에 대한 유한 차이 또는 표준 공식을 사용하여 분산을 계산하는 경우 유사한 숫자 간의 차이에 대한 계산으로 인해 정밀도가 손실됩니다.반올림 오차가 누적되어 QR 또는 LU 분해, 콜레스키 분해, SVD 등을 사용하기 때문에 선형 시스템을 해결하기 위한 Gau algorithm 알고리즘은 좋지 않습니다.부동 소수점 숫자의 덧셈은 연관성이 없습니다.데노멀, 무한 및 NaN 값이 있습니다.a + b - a b b.

  • 문자열:문자, 코드 포인트 및 코드 단위의 차이.다양한 운영 체제에서 Unicode를 구현하는 방법, Unicode 인코딩.C++에서는 임의의 Unicode 파일명으로 파일을 포터블 방식으로 열 수 없습니다.

  • 스레드가 없는 경우에도 레이스 조건:파일이 존재하는지 여부를 테스트하면 결과는 언제든지 무효가 될 수 있습니다.

  • ERROR_SUCCESS= = 0

빌트인 데이터 타입에 관한 몇 가지 사항은 다음과 같습니다.

  • char ★★★★★★★★★★★★★★★★★」signed char 가지됩니다(다만, 두 가지 유형으로 구분됩니다.int ★★★★★★★★★★★★★★★★★」signed int을 이용하다
  • 부호 있는 정수는 2의 보수를 사용할 필요가 없습니다.한 사람의 보와 기호+크기도 음수를 나타내는 유효한 표현이다.이것에 의해, 음수를 포함한 비트 조작이 실장 정의됩니다.
  • 범위 밖의 정수를 서명된 정수 변수에 할당하면 동작이 구현 정의됩니다.
  • C90에서는-3/5할 수 있다0 ★★★★★★★★★★★★★★★★★」-1으로 반올림하는 위에서만 1개의 오퍼랜드가 음수인 경우 0으로 반올림하는 것은 C99 위, C++0x 위에서만 보장됩니다.
  • 빌트인 타입의 정확한 사이즈는 보증되지 않습니다..int최소 16비트의long최소 32비트가 있다.long long는 최소 64비트를 가지고 있습니다.afloat는 적어도 최상위 소수점 이하 6자리를 올바르게 나타낼 수 있습니다. a.double는 최소 10자리 이상의 유효 소수점을 올바르게 나타낼 수 있습니다.
  • IEEE 754는 부동소수점 번호를 나타내기 위해 필수는 아닙니다.

물론 대부분의 기계에는 2개의 보완 장치가 있고 IEEE 754 플로트가 있습니다.

편집: 프로그램의 마지막 버전으로 업데이트됨

Solaris-SPARC

gcc 3.4.6 (32비트)

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

gcc 3.4.6 (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.
..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

SUN Studio 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

SUN Studio 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

모드텍스트 모드)를 사용할 수 .fopen("filename", "r")모든 종류의 텍스트 파일을 읽습니다.

이론상으로는 이 방법이 잘 작동하지만ftell()라이브러리의 에서는 UNIX 형식의 행이 텍스트파일에 ftell()유효하지 않은 값이 반환되는 경우가 많습니다. 모드바이너리 )를 입니다.fopen("filename", "rb")를 참조해 주세요.

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

에서 할 수 있는 은 C++로 .structC에서 할 수 있는 것에 한정되어 있습니다. C'C++'가 됩니다.structa a 같다class기본적으로는 모든 것이 공개되어 있다는 점만,

C++ 구조:

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


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

protected:
  void Testing2();
};

서로 다른 시스템의 표준 산술 함수는 동일한 결과를 제공하지 않습니다.

32비트 x86의 Visual Studio Express 2010.

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

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

에는 Codepad가 .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

과도한 양의 오른쪽 시프트가 표준으로 허용되나요, 아니면 테스트할 가치가 있나요?

Standard C는 다음 프로그램의 동작을 규정합니까?

void print_string(char *st){char ch;while(ch = *st++) != 0)putch(ch); /* 정의되어 있다고 가정합니다*/}int main(메인){print_string("Hello");
0을 반환한다.}

적어도 1개의 컴파일러에서 print_string에 대한 인수가 "char const *"가 아닌 한 이 코드는 실패합니다.그 규격은 그러한 제한을 허용하고 있는가?

정렬되지 않은 'int'에 대한 포인터를 생성할 수 있는 시스템과 그렇지 않은 시스템이 있습니다.시험해 볼 가치가 있을 거야

참고로 C 스킬을 Java로 번역해야 하는 분들을 위해 몇 가지 gotcha를 소개합니다.

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

Java에서 char는 16비트, signed, byte는 8비트, signed입니다.

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

long은 항상 64비트이며 참조는 32비트 또는 64비트(32GB를 초과하는 애플리케이션이 있는 경우) 64비트 JVM은 일반적으로 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));

수집 및 어레이의 크기는 JVM이 32비트인지 64비트인지에 관계없이 항상 32비트입니다.

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비트, short는 16비트, int는 32비트, long은 64비트입니다.

언급URL : https://stackoverflow.com/questions/3457967/what-belongs-in-an-educational-tool-to-demonstrate-the-unwarranted-assumptions-p

반응형