国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

精華:C++編程新手錯誤語錄(續(xù)一)

2019-11-17 05:03:39
字體:
來源:轉載
供稿:網(wǎng)友
  廢話不說,直接進入正題,本文承接先前發(fā)布的《C/C++編程新手錯誤語錄》(http://www.pconline.com.cn/pcedu/empolder/gj/c/0508/691597.Html),繼續(xù)歸納錯誤語錄。
(8)“我想用malloc”、“我用不好malloc”
  來看看一個變態(tài)程序:
/* xx.c:xx模塊實現(xiàn)文件 */
int *pInt;
/* xx模塊的初始化函數(shù) */
xx_intial()
{
pInt = ( int * ) malloc ( sizeof( int ) );
...
}
/* xx模塊的其他函數(shù)(僅為舉例)*/
xx_otherFunction()
{
*Int = 10;
...
}
  這個程序定義了一個全局整型變量指針,在xx模塊的初始化函數(shù)中對此指針動態(tài)申請內(nèi)存,并將pInt指向該內(nèi)存首地址,并在xx模塊的其他函數(shù)中都使用pInt指針對其指向的整數(shù)進行讀取和賦值。

  這個程序讓我痛不欲生了好多天,扼腕嘆息!這是我母校計算機系一位碩士的作品!作者為了用上malloc,拼命地把本來應該用一個全局整型變量擺平的程序活活弄成一個全局整型指針并在初始化函數(shù)中“動態(tài)”申請內(nèi)存,自作聰明而正好暴露自己的無知!我再也不要見到這樣的程序。

  那么malloc究竟應該怎么用?筆者給出如下規(guī)則:
  規(guī)則1 不要為了用malloc而用malloc,malloc不是目的,而是手段;

  規(guī)則2 malloc的真正內(nèi)涵體現(xiàn)在“動態(tài)”申請,假如程序的特性不需動態(tài)申請,請不要用malloc;

  上面列舉的變態(tài)程序完全不具備需要動態(tài)申請的特質,應該改為:
/* xx.c:xx模塊實現(xiàn)文件 */
int example;
/* xx模塊的初始化函數(shù) */
xx_intial()
{
...
}
/* xx模塊的其他函數(shù)(僅為舉例) */
xx_otherFunction()
{
example = 10;
...
}
更多文章 更多內(nèi)容請看C/C++技術專題  java編程開發(fā)手冊專題,或
  規(guī)則3 什么樣的程序具備需要動態(tài)申請內(nèi)存的特質呢?包含兩種情況:
  (1)不知道有多少要來,來了的又走了
  不明白?這么說吧,譬如你正在處理一個報文隊列,收到的報文你都存入該隊列,處理完隊列頭的報文后你需要取出隊列頭的元素。

  你不知道有多少報文來(因而你不知道應該用多大的報文數(shù)組),這些來的報文處理完后都要走(釋放),這種情況適合用malloc和free。

  (2)慢慢地長大
  譬如你在資源受限的系統(tǒng)中編寫一文本編輯器程序,你怎么做,你需要這樣定義數(shù)組嗎?
  char str[10000];  不,你完全不應該這么做。即使你定義了一個10000字節(jié)大的字符串,用戶假如輸入10001個字符你的程序就完完了。

  這個時候適合用malloc,因為你根本就不知道用戶會輸入多少字符,文本在慢慢長大,因而你也應慢慢地申請內(nèi)存,用一個隊列把字符串存放起來。

  那么是不是應該這樣定義數(shù)據(jù)結構并在用戶每輸入一個字符的情況下malloc一個CharQueue空間呢?
typedef strUCt tagCharQueue

{
char ch;
struct tagCharQueue *next;
}CharQueue;
  不,這樣做也不對!這將使每個字符占據(jù)“1+指針長度”的開銷。

  正確的做法是:
typedef struct tagCharQueue
{
char str[100];
struct tagCharQueue *next;
}CharQueue;
  讓字符以100為單位慢慢地走,當輸入字符數(shù)達到100的整數(shù)倍時,申請一片CharQueue空間。

更多文章 更多內(nèi)容請看C/C++技術專題  Java編程開發(fā)手冊專題,或
  規(guī)則4 malloc與free要成對出現(xiàn)
  它們是一對恩愛夫妻,malloc少了free就必然會慢慢地死掉。成對出現(xiàn)不僅體現(xiàn)在有多少個malloc就應該有多少個free,還體現(xiàn)在它們應盡量出現(xiàn)在同一函數(shù)里,“誰申請,就由誰釋放”,看下面的程序:
char * func(void)
{
char *p;
p = (char *)malloc(…);
if(p!=NULL)
…; /* 一系列針對p的操作 */
return p;
}
/*在某處調用func(),用完func中動態(tài)申請的內(nèi)存后將其free*/
char *q = func();

free(q);
  上述代碼違反了malloc和free的“誰申請,就由誰釋放”原則,代碼的耦合度大,用戶在調用func函數(shù)時需確切知道其內(nèi)部細節(jié)!正確的做法是:
/* 在調用處申請內(nèi)存,并傳入func函數(shù) */
char *p=malloc(…);
if(p!=NULL)
{
func(p);

free(p);
p=NULL;
}
/* 函數(shù)func則接收參數(shù)p */
void func(char *p)
{
… /* 一系列針對p的操作 */
}
  規(guī)則5 free后一定要置指針為NULL,防止其成為“野”指針

(9)“函數(shù)add編譯生成的符號就是add”
int add(int x,int y)
{
return x + y;
}
float add(float x,float y)
{
return x + y;
}
更多文章 更多內(nèi)容請看C/C++技術專題  Java編程開發(fā)手冊專題,或
  即便是在C語言中,add函數(shù)被多數(shù)C編譯器編譯后在符號庫中的名字也不是add,而是_add。
而在C++編譯器中,int add(int x,int y)會編譯成類似_add_int_int這樣的名字(稱為“mangled name”),float add(float x,float y)則被編譯成_add_float _float,mangled name包含了函數(shù)名、函數(shù)參數(shù)數(shù)量及類型信息,C++依靠這種機制來實現(xiàn)函數(shù)重載。

  所以,在C++中,本質上int add( int x, int y )與float add( float x, float y )是兩個完全不同的函數(shù),只是在用戶看來其同名而已。

  這就要求初學者們能透過語法現(xiàn)象看問題本質。本質上,語言的創(chuàng)造者們就是在玩各種各樣的花樣,以使語言具備某種能力,譬如mangled name花樣的目的在于使C++支持重載。而C語言沒有玩這樣的花樣,所以int add( int x, int y )與float add( float x, float y )不能在C程序中同時存在。

(10)“沒見過在C語言中調用C++的函數(shù)”、“C/C++不能調用Basic、Pascal語言的函數(shù)”
  這又是一個奇天下之大怪的問題,“打死我都不相信C、C++、basic、pascal的函數(shù)能瞎調來調去”,可是有句話這么說:
  沒有你見不到的,只有你想不到的!

  既然芙蓉姐姐也有其聞名天下的道理,那么C、C++、Basic、Pascal的函數(shù)為什么就不能互相調用呢?
  能!

  你可以用Visual C++寫一個DLL在Visual Basic、Delphi(Pascal的孫子,Object Pascal的兒子)中調用,也可以在Visual Basic、Delphi中寫一個DLL在Visual C++中調用不是?


  讓我們來透過現(xiàn)象看本質。首先看看函數(shù)的調用約定(以Visual C++來說明):
  (1) _stdcall調用
  _stdcall是Pascal程序的缺省調用方式,參數(shù)采用從右到左的壓棧方式,被調函數(shù)自身在返回前清空堆棧。
  WIN32 Api都采用_stdcall調用方式,這樣的宏定義說明了問題:
  #define WINAPI _stdcall  按C編譯方式,_stdcall調用約定在輸出函數(shù)名前面加下劃線,后面加“@”符號和參數(shù)的字節(jié)數(shù),形如_functionname@number。

更多文章 更多內(nèi)容請看C/C++技術專題  Java編程開發(fā)手冊專題,或
  (2) _cdecl調用
  _cdecl是C/C++的缺省調用方式,參數(shù)采用從右到左的壓棧方式,傳送參數(shù)的內(nèi)存棧由調用者維護。_cedcl約定的函數(shù)只能被C/C++調用,每一個調用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比調用_stdcall函數(shù)的大。

  由于_cdecl調用方式的參數(shù)內(nèi)存棧由調用者維護,所以變長參數(shù)的函數(shù)能(也只能)使用這種調用約定。關于C/C++中變長參數(shù)(…)的問題,筆者將另文詳述。

  由于Visual C++默認采用_cdecl 調用方式,所以VC中中調用DLL時,用戶應使用_stdcall調用約定。
  按C編譯方式,_cdecl調用約定僅在輸出函數(shù)名前面加下劃線,形如_functionname。

  (3) _fastcall調用
  _fastcall調用較快,它通過CPU內(nèi)部寄存器傳遞參數(shù)。

  按C編譯方式,_fastcall調用約定在輸出函數(shù)名前面加“@”符號,后面加“@”符號和參數(shù)的字節(jié)數(shù),形如@functionname@number。

  要害字_stdcall、_cdecl和_fastcall可以直接加在函數(shù)前,也可以在Visual C++中設置,如圖1。
精華:C++編程新手錯誤語錄(續(xù)一)  圖1 在VC中設置函數(shù)調用約定  在創(chuàng)建DLL時,一般使用_stdcall調用(Win32 Api方式),采用_functionname@number命名規(guī)則,因而各種語言間的DLL能互相調用。也就是說,DLL的編制與具體的編程語言及編譯器無關,只要遵守DLL的開發(fā)規(guī)范和編程策略,并安排正確的調用接口,不管用何種編程語言編制的DLL都具有通用性。

  推而廣之,假如有這樣一個IDE開發(fā)環(huán)境,它能識別各種語言,所有語言采用相同的調用約定和命名規(guī)則,一個軟件內(nèi)各種語言書寫的函數(shù)將能互相調用!

  這個世界上可能永遠不需要這樣一個IDE。

(11)“英語、數(shù)學不好就學不好C/C++”
更多文章 更多內(nèi)容請看C/C++技術專題  Java編程開發(fā)手冊專題,或
  這也許是20世紀最大的謊言,這句話最先是哪位大師的名人名言已無可考證,可此后一批批的人被它誤導。許多初學者因為這句話被嚇倒,放棄了做程序員的理想。
還有許多后來成為優(yōu)秀程序員的人,在他們的成長過程中并沒有依靠深奧的數(shù)學,可他們還是在總結經(jīng)驗時制造恐慌,號稱一定要具備高深的數(shù)學知識,唯恐別人笑話其學術水平不高。

  在下則認為,大多數(shù)情況下,程序設計不需要太深奧的數(shù)學功底,除非你所從事的程序設計涉及特定的專業(yè)領域(如語音及圖像處理、數(shù)字通信技術等)。在下這一觀點也許是革舊立新,而革命必然要流血犧牲(譚嗣同),所以恭候大家板磚。

  那么英語在C/C++的學習中處于什么地位呢?那就是能看懂資料,看懂MSDN。

  學編程的終極之道不在看書,而在大量地不斷地實踐。

(12)“C++太難了,我學不會”

  又不知是誰的悲觀論調,許多初學者被C++嚇倒,“太難了,我學不好”,如弱者自憐。假如C++真的難到學不會,那么C++的創(chuàng)造者們所從事的工作豈不是“非人力所能及也”?  
 
  在下認為,學習C++的態(tài)度應該是:戰(zhàn)略上藐視它,戰(zhàn)術上重視它,要敢于勝利(《毛主席語錄》)。當然也不可輕敵,不能因為把握了一點皮毛就以為自己牛B轟轟了(筆者曾經(jīng)牛B轟轟了好一陣子,現(xiàn)在想來,甚覺當時幼稚)。

  假如你征服了C++,透徹理解了C++的語言特性及STL,那么,其他語言想不被你征服都難了。

  本回書著落此處,更多錯誤語錄,當然是待續(xù)。
更多文章 更多內(nèi)容請看C/C++技術專題  Java編程開發(fā)手冊專題,或

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 富民县| 徐州市| 修武县| 新乐市| 石嘴山市| 庆城县| 响水县| 高碑店市| 五大连池市| 水城县| 上犹县| 舟曲县| 安徽省| 叙永县| 武城县| 丰宁| 新干县| 登封市| 贵阳市| 万山特区| 定兴县| 安庆市| 集安市| 梁山县| 团风县| 宜章县| 遵义县| 宁陵县| 洞头县| 额尔古纳市| 永丰县| 饶阳县| 贵州省| 会东县| 阳春市| 长治市| 慈利县| 文昌市| 辽源市| 衡阳县| 浦县|