本文記錄了最近學習過程中,以及在編碼過程中,感受到的比較好的編程習慣。如果有什麼地方您覺得不妥,還請留言指出。
解釋:對於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;
}
解釋:這個錯誤曾經導致了整個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;
}
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)
{}