小计良好的编程习惯(1)

本文记录了最近学习过程中,以及在编码过程中,感受到的比较好的编程习惯。如果有什么地方您觉得不妥,还请留言指出。


  1. 变量(普通变量和指针)的初始化。

    解释:对于C/C++来说,声明的变量没有初始化,那么里面的值是有的(以前该内存的数值),所以对于自加自减的运算,在这里容易出错。而指针更是危险,声明的指针没有赋值的话,里面也是有值的,此时你不知道声明的指针指向哪里,等到你使用的时候,才会给指针赋值,那么在这期间,如果你使用了指针,修改了里面的东西,那就是无知的修改,是最可怕的。代码理解如下:

    #include <QCoreApplication>
    #include <QDebug>
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        int i;
        qDebug()<<++i;//4203055
        int *p;
        qDebug()<<p;//0x22ff88
        p = (int *)malloc(sizeof(int)*1);
        qDebug()<<p;//0x847b38
        //下面是良好的习惯
        int j=0;
        qDebug()<<++j;//1
        int *pointer=NULL;
        qDebug()<<pointer;//0x0
        pointer = (int *)malloc(sizeof(int)*1);
        qDebug()<<pointer;//0x847b48
        qDebug()<<"Hello word!";
        
        return a.exec();
    }
  2. 指针的释放与置空

    程序中为指针动态分配的内存,在程序结尾的时候,不仅养成释放内存的习惯,还要养成为指针置空的习惯。也就说,结尾你把指针的内存释放了,但是该指针还是指向这里的,这样就存在了一个安全隐患,所以要置空。代码展示如下:

    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    int main()
    {
        int *pointer=NULL;//指针初始要为NULL
        pointer = (int *)malloc(sizeof(int)*1);
        cout << "Hello World! I am over!" << endl;
        //以下为良好的指针结束方式(来也空空去也空空)
        free(pointer);
        pointer = NULL;
        return 0;
    }
  3. malloc申请的动态内存,坑多多,不要用strlen测量

    解释:这个错误曾经导致了整个QQ群的轰动,其实当你查看一下你动态开辟的内存的里面的内容的时候,你就会恍然大悟。先简单解释一下,主要是C语言的strlen函数没有搞清楚。我们所使用的所有内存,如果没有初始化,那么里面肯定会有内容的(计算机原理),包括了我们动态开辟的内存,而strlen函数的作用,测量字符串的长度(以'\0'结束).未知的世界中永远存在着未知的可能,未知的内存中,也许中间部分就包括了'\0'奥。那么使用strlen测量,就会有让人意外的结果了。代码展示如下:

    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    int main()
    {
        char *pointer=NULL;//指针初始要为NULL
        pointer = (char *)malloc(sizeof(char)*15);
        cout<<"string:"<<strlen(pointer);//我的输出3
        cout<<"value:"<<pointer;
        cout<<endl;
        char *pointer1="You Love Me.";//12
        cout<<"string1:"<<strlen(pointer1);
        cout<<endl;
        return 0;
    }
    01
  4. while(NULL != p && item->data > p->data )小心判断条件中的断路现象,这2个子条件是不能调换的。

    解释:在C/C++中判定语句有一种特性,叫做“断路”。比如:if(条件1&&条件2)这个判定,如果要想为真,则2个条件都必须为真。判定如果为假,在实际中,如果条件1为假的话,那么程序就不会去判定条件2的真假了。这就是断路现象。同理,if(条件1&&条件2)只要条件1为真,就不会判定第二个条件了。那么我们的实例会产生怎样的错误呢?首先我们这句while(NULL != p && item->data > p->data )是正确的,但是如果你把2个条件前后交换,那么就制造了一个bug.我的思路是,首先判断p的指向是否存在,存在的话,然后p->data是否为真,如果前后2个条件调换的话,那么当p=NULL的话,p->data会在哪里呢?你去哪里读数据?程序就这样被你玩儿死了。

  5. 判断条件句中的变量比较
    #include <iostream>
    using namespace std;
    //下面每个变量都与零值比较,选择最优的方法
    int main()
    {
        bool flag;
        if(flag == true){}
        if(flag == false){}
        //bool类型的变量应该选择下面的规范
        if(flag){}//这种方法最优,因为true的值不确定
        if(!flag){}
    
        int value;
        if(value == 0){}//这种方法好,下面的会让人误解是布尔类型
        if(value != 0){}
    
        if(value){}
        if(!value){}
    
        float x;
        if(x == 0){}
        if(x != 0){}
        //下面的方法好,因为所有的float和double类型都有精度的,所以转化为下面的形式比较
        if((x >= -EPSINON)&&(x <= EPSINON)){}
        if((X < -EPSINON) || (x > EPSINON)){}
    
        int *p;
        if(p == NULL){}//这种好
        if(p != NULL){}
    
        if(p == 0){}
        if(p != 0){}
    
        //有的时候,还会这样写(想一想这种方法的好处)
        if(0 == value){}
        if(NULL == p){}
        cout << "Hello World!" << endl;
        return 0;
    }
  6. 判断条件中不要使用含有副作用的语句

    解释:首先,何为副作用,就是会改变程序状态的语句。看代码实例:

    if('Y'==getchar() || 'y' == getchar())//getchar()从缓冲区中,读一个少一个,那么读的过程中,程序的状态是不是改变了,那么这就容易发生错误。
    {}
    //规范的如下:
    char ch=toupper(getchar());//自己体会一下
    if('Y'==ch)
    {}
  7. 在定义函数或者变量名的时候,小心和关键字冲突或者标准函数冲突。
  8. 函数中的形参,在函数体中不改变的话,设置为const常量
  9. 对于函数中传递过来的参数,要进行安全检查
  10. 变量的定义应该“何时使用,何时定义,何地使用,何时定义”,变量定义的位置,应该和使用的地方紧凑一点。

结语:

良好的编程习惯只有在你写程序的时候才能完全的体会到。同时,如果您有更好的理解,可以在下面留言,一起学习进步。

posted @ 2015-05-25 15:59  [0]  阅读(434)  评论(0编辑  收藏  举报