您的位置:首页 > 编程语言

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

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

变量(普通变量和指针)的初始化。
解释:对于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();
}


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

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


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






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
会在哪里呢?你去哪里读数据?程序就这样被你玩儿死了。

判断条件句中的变量比较

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


判断条件中不要使用含有副作用的语句
解释:首先,何为副作用,就是会改变程序状态的语句。看代码实例:

if('Y'==getchar() || 'y' == getchar())//getchar()从缓冲区中,读一个少一个,那么读的过程中,程序的状态是不是改变了,那么这就容易发生错误。
{}
//规范的如下:
char ch=toupper(getchar());//自己体会一下
if('Y'==ch)
{}


在定义函数或者变量名的时候,小心和关键字冲突或者标准函数冲突。

函数中的形参,在函数体中不改变的话,设置为const常量

对于函数中传递过来的参数,要进行安全检查

变量的定义应该“何时使用,何时定义,何地使用,何时定义”,变量定义的位置,应该和使用的地方紧凑一点。

结语:

良好的编程习惯只有在你写程序的时候才能完全的体会到。同时,如果您有更好的理解,可以在下面留言,一起学习进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: