小计良好的编程习惯(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;
    }

  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. 变量的定义应该“何时使用,何时定义,何地使用,何时定义”,变量定义的位置,应该和使用的地方紧凑一点。


结语:

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

时间: 2024-10-05 10:45:06

小计良好的编程习惯(1)的相关文章

traits技法小计

在学习算法导论的时候,对于各数据结构,自然是实现一个才算掌握,工具当然是template编程,但是自己的demo经常存在很多问题,比如没有给出迭代器啊,操作符重载不够啊等等设计上的问题,而某些问题实际上是从设计之初就该考虑的大框架,而非小细节.对于C++而言,STL无疑是最佳的参考资料,侯捷先生的STL源码剖析一书给我们良好的示范,而直接从第四章开始看会云里雾里,无法得其精髓,因此在学习算法之余决定尾随侯捷先生脚步,学习STL traits技法,从而可以从STL中学到更多的数据结构实现. 收获自

防御性编程习惯:求出链表中倒数第 m 个结点的值及其思想的总结

防御性编程习惯 程序员在编写代码的时候,预料有可能出现问题的地方或者点,然后为这些隐患提前制定预防方案或者措施,比如数据库发生异常之后的回滚,打开某些资源之前,判断图片是否存在,网络断开之后的重连次数或者是否连接备用网络,除法运算中的除数问题,函数或者类在接受数据的时候的过滤情况,比如如果输入一个指针参数,是否需要判断是不是空指针?输入一个字符串参数,是否需要判断字符串空否……总的来说就是防止出现不可预见的事情,设计出鲁棒性的代码. 看下面的例子 输入一个链表,输出链表中倒数第 m 个结点额内容

黄金点游戏的尝试与编程习惯的改变尝试

这一次,软件工程老师给我们所有同学出了个难题,什么呢?结对编程!说到结对编程,我想至少对于我来说是一个完全陌生的领域,为什么这么说呢?原来的C语言作业也好,C++作业也好,我大多是单枪匹马的自己在做前期的构想,中期的编程调试,到后期的查找错误修改问题,即使是有其他人的参与也只限于我腆着脸去找同班同学或者其他班的大神求助,但大体上还是我一个人在战斗.但是这次不一样,这次按照老师布置的作业要求,需要结对的两人坐在一台电脑前,合用一个键盘,一个鼠标,共同编写一个程序代码.这样,编程的全过程就变得和原来

vim 小计

vim 小计 现在经常要用到vim,感觉它和一般的编辑器很不同,的确是非常难却又非常强大的东西,我之前掌握的皮毛显然是不能再提高生产力了,想着如果能学好应该是收益颇丰,现在记下我这周学的东西: Navigate: 之前一直只知道jkhl,0^$,ctrl+F, ctrl+B,现在知道w e b 和H M L ,方便多了.还有%来查看括号,对编程很有帮助. Insert: 之前只知道i,现在知道a, o, I, A, O Delete: 之前只知道dd,现在知道x, dw等组合 Undo: 之前只

c语言之良好的编程习惯(三)

1.同一个文件在每次调用输入输出函数时,都将产生一个新的ferror()函数值,因此在调用输入输出函数后应该立即检查ferror的函数值,否则信息会丢失. 2.使用临时文件中需要考虑以下两个问题. <1>保证临时文件间的文件名不互相冲突 <2>保证临时文件中的内容不被其他用户偷看.删除.修改. 3.使用目录时需要考虑以下几点. <1>信息量大小.目录适合存放小的信息量,可以利用指针指向大的文件. <2>信息的类型.目录通常是属性的信息. <3>读

漫谈C++:良好的编程习惯与编程要点

该篇文章转载自这里写链接内容 以良好的方式编写C++ class 假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯. ① Header(头文件)中的防卫式声明 complex.h: ifndef __COMPLEX__ # define __COMPLEX__ class complex { } # endif 防止头文件的内容被多次包含. ② 把数据放在private声明下,提供接口访问数据 # ifndef __COMPLEX__ # define __COMP

汽车仪表是如何计算总计里程和小计里程的?

现在汽车仪表大部分的总计里程和小计里程都是显示在屏幕上的,这包括段码屏.点阵屏.TFT彩屏等,虽然显示形式不一样,但是从业务需求和软件应用层的实现策略来讲,原理应该都是通用的.本文不涉及具体车型,仅对一般的业务逻辑作介绍,一是为了自己总结记录,二是期望吸引同行或爱好者交流. 1.总计里程 ODO(Total Odometer )即总计里程,顾名思义,主要作用是记录汽车总的行驶里程,一般来讲,在用户使用过程中是无法对其修改或清零的,因为它是对二手汽车价值评估的一项重要数值,当然随意篡改这一数据也是

java的编程习惯

1.注释 描述代码的文字 说明 不参与编译(给人看) 提高程序的可读性 文档习惯 // 单行注释 /* 多行注释 /* */ 不允许嵌套 */ /** 多行注释 配合JavaDoc工具使用 用来生成API文档 */ 2.缩进 换行和空格 表达程序的结构 可读性 每行一句代码 每进入一个代码块 {} , 缩进一次 同级代码列对齐 3.标识符命名 语法: 字母 数字 _ $ 组成,数字不能开头 大小写敏感 不能使用关键字和保留字(goto const) 习惯: 望文知义 大小写 类名 单词首字母大写

编程习惯

源文件文件名必须和 公开的类名相同(包过大小写)编程习惯 可读性 1.注释 加一些代码描述语言 //单行注释 /* */ 多行注释 /** */ 多行注释2.每个语句缩进3.标示符 语法:字母.数字._ .$ 数字不能开头 严格区分大小写 不能使用关键字和保留字(goto .const) 类名:单词首字母大写 HelloWorld 变量.方法名:第一个单词首字母小写,后面单词首字母大写 helloWorld 包名:全小写 常量:全大写