现在的位置: 首页 > 综合 > 正文

编程错误集锦(长期更新)

2018年04月21日 ⁄ 综合 ⁄ 共 1960字 ⁄ 字号 评论关闭

       1.使用标准库快排函数时浮点数的比较

//错误样例
int Mycmp(const void *a, const void *b)     
{
    return *(double *)a - *(double *)b;
}

//正确样例
int Mycmp(const void *a, const void *b)     
{
    if (*(double *)a > *(double *)b)
    {
        return 1;
    }
    return -1;
}

       解释:标准库里的快排函数中的自定义比较函数的返回值类型为int。错误样例中的函数定义返回类型为int,而实际返回类型为double,这样会造成将double类型的数据赋值给int类型的数据的效果,也就是数据丢失。浮点型赋值给整型时小数位的数据会丢失并且不会进行四舍五入,所以0.9赋值给int类型的数据时int类型得到的值为0。


       2.使用if语句进行变量值的判断

//错误样例
if (x = 5)      //普通写法
{
    //Do something;
}

if (5 = x)      //好的写法
{
    //Do something;
}

//正确样例
if (x == 5)     //普通写法
{
    //Do something;
}

if (5 == x)     //好的写法
{
    //Do something;
}
       解释:当我们需要写“==”符号时却写成了“=”是一种十分常见的编程失误。但是有一种技巧性写法可以让我们更容易发现此类错误。那就是把常量值写在左边,变量写在右边。很明显好的写法中的错误样例编译不会通过,因为赋值运算符的左值不能为常量或表达式,而普通写法的错误样例编译却可以通过,这样的错误不容易被发现。

       3.整型数做除法的值赋给浮点数

//错误样例
double aver;
int sum, n;
aver = sum / n;
//或者
aver = sum / 10;

//正确样例
double aver;
int sum, n;
aver = (double)sum / n;
//或者
aver = sum / 10.0;

       解释:当我们使用整数之间的除法想要得到浮点数这样的结果,很容易直接把整数除法的结果赋给浮点数,事实上在C/C++中这样的结果是先得到整数除法的结果再把结果强转为浮点数,这样导致了数据的错误,应该首先将其中整数强制转换为浮点数,这样才会进行浮点数的运算从而得到正确的浮点数结果,避免了数据的错误。


       4.取一个十进制数某一位的次方

//比如取一个3位数的百位然后求它的三次方

//错误样例
a = x / 100 * x / 100 * x / 100;

//正确样例
a = (x / 100) * (x / 100) * (x / 100);

       解释:这是在做一道ACM题中发现的错误,怎么提交都没有过,然后把错误样例改成正确的样例就过了,我错误的认为了不加括号进行运算的结果与加括号是一样的,很容易举一个反例:求425的百位数的三次方应该是64,错误样例的结果却是72,因为百位数对下一个x的十位数相乘造成了进位从而导致结果的不同。所以,不要图方便不写小括号。


       5.memset函数的使用

#define N 100
int num[N];
char ch[N];

//正确用法
memset(num, 0, sizeof(num));
memset(num, -1, sizeof(num));
memset(ch, 100/*只要是在char类型的范围之内*/, sizeof(ch));

//错误用法
memset(num, 1/*或者其它非0和-1的数*/, sizeof(num));

       解释:因为整数在计算机的存储方式是以二进制补码存储的,其中正数的二进制补码就是本身的二进制原码存储,而负数的补码的则是二进制原码的反码再加一得到的。因为符号位1代表负,0代表正,所以0在计算机中每一位的值都是0,-1在计算机中每一位的值都是1。memset函数的功能是把从第一参数为指定内存开始处向后的第三参数的字节数的每一个字节内存的值都设置为第二参数的值,所以在int型数组中集体赋值只有0和-1是有效的,因为int型变量所占的字节数一般是2或者4个字节,但是如果是在char型数组中,那么集体赋值在整个char类型范围都能有效,因为char类型变量所占的字节数就是1。

       6.int与long或long long类型的赋值

// 正确写法
long long x = 1LL << 32;

// 错误写法
long long x = 1 << 32;

       解释:上面的样例中,1左移32位已经超过了4字节int类型的范围,目前绝大部分计算机没有给整数后面写英文后缀时都是默认为int型,int类型的1左移32位后还是int型,只不过结果已经溢出了,然后才强制转换赋值给long long类型,所以会导致x赋值错误。正确写法应该要在1后面写LL以声明该常数为long
long类型常数,这样一来运算就都是long long类型的运算了,就不会导致溢出。


抱歉!评论已关闭.