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