在什么教育工具来演示无根据的假设人们在C / C ++属于? [英] What belongs in an educational tool to demonstrate the unwarranted assumptions people make in C/C++?

查看:113
本文介绍了在什么教育工具来演示无根据的假设人们在C / C ++属于?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想prepare了那么一点点的教育工具,这应有助于初学者(和中间)程序员承认和挑战在C,C ++的无根据的假设和他们的平台。

I'd like to prepare a little educational tool for SO which should help beginners (and intermediate) programmers to recognize and challenge their unwarranted assumptions in C, C++ and their platforms.

例如:


  • 整数环绕

  • 每个人都有ASCII

  • 我可以存储在一个void *的函数指针

我计算过,一个小的测试程序可以在各种平台上运行,它运行的似是而非的假设这是,从我们的经验,所以,平时很多没有经验的/ semiexperienced主流开发商提出并记录他们在不同的突破方式机器。

I figured that a small test program could be run on various platforms, which runs the "plausible" assumptions which are, from our experience in SO, usually made by many inexperienced/semiexperienced mainstream developers and record the ways they break on diverse machines.

这样做的目的不是证明它是安全做一些事情(这将是不可能的事,测试只能证明什么,如果他们打破),而是以证明即使是最uncom prehending个人如何最不起眼的前pression不同的机器上破,如果它有一个未定义的或实现定义的行为。

The goal of this is not to prove that it is "safe" to do something (which would be impossible to do, the tests prove only anything if they break), but instead to demonstrate to even the most uncomprehending individual how the most inconspicuous expression break on a different machine, if it has a undefined or implementation defined behavior..

要做到这一点,我想问问你:

To achieve this I would like to ask you:


  • 怎么能这样的想法得到改善呢?

  • 哪些测试将是一件好事,他们应该看怎么样?

  • 您将运行在平台上测试你可以把你的手和后的结果,让我们最终与平台的数据库,它们之间的区别,以及为什么这种差异是允许的?

下面是当前版本为测试玩具:

Here's the current version for the test toy:

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


哦,我做了这个社会的维基从一开始,因为我想,人们希望他们读这个当编辑我的喋喋不休。


Oh, and I made this community wiki right from the start because I figured that people want to edit my blabber when they read this.

更新感谢您​​的输入。我从你的答案增加了一些案件,会看到,如果我可以成立一个github上这个像格雷格建议。

UPDATE Thanks for your input. I've added a few cases from your answers and will see if I can set up a github for this like Greg suggested.

更新
我已经为这个GitHub库,该文件是gotcha.c

UPDATE: I've created a github repo for this, the file is "gotcha.c":

请用补丁或新的想法回答在这里,所以他们可以讨论或澄清这里。我将它们合并到gotcha.c呢。

Please answer here with patches or new ideas, so they can be discussed or clarified here. I will merge them into gotcha.c then.

推荐答案

SUBEX pressions,包括评价的顺序

The order of evaluation of subexpressions, including


  • 函数调用的参数和

  • 运营商的操作数(例如, + - = * / )的除外:

    • 二元逻辑运算符(&放大器;&安培; || ),

    • 三元条件操作符()和

    • 逗号(

    • the arguments of a function call and
    • operands of operators (e.g., +, -, =, * , /), with the exception of:
      • the binary logical operators (&& and ||),
      • the ternary conditional operator (?:), and
      • the comma operator (,)

      未指定

      例如

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

      这篇关于在什么教育工具来演示无根据的假设人们在C / C ++属于?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆