必胜高考网_全国高考备考和志愿填报信息平台

必勝高考網 > 計算機類 > 計算機等級 > 資訊 >

全國計算機等級考試四級上機編程修養(下)

時間: 家輝2 資訊

  }else{

  /* 輸出錯誤信息 */

  printf("error ......\n");

  return ( FALSE );

  }

  這種結構很不好,特別是如果“正常處理代碼”很長時,對于這種情況,最好不要用else。先判斷錯誤,如:

  if ( ch < ’0’ || ch > ’9’ ){

  /* 輸出錯誤信息 */

  printf("error ......\n");

  return ( FALSE );

  }

  ......

  這樣的結構,不是很清楚嗎?突出了錯誤的條件,讓別人在使用你的函數的時候,第一眼就能看到不合法的條件,于是就會更下意識的避免。

  7、頭文件中的#ifndef

  ——————————

  千萬不要忽略了頭件的中的#ifndef,這是一個很關鍵的東西。比如你有兩個C文件,這兩個C文件都include了同一個頭文件。而編譯時,這兩個C文件要一同編譯成一個可運行文件,于是問題來了,大量的聲明沖突。

  還是把頭文件的內容都放在#ifndef和#endif中吧。不管你的頭文件會不會被多個文件引用管你的頭文件會不會被多個文件引用,你都要加上這個。一般格式是這樣的:

  #ifndef <標識>

  #define <標識>

  ......

  ......

  #endif

  <標識>在理論上來說可以是自由命名的,但每個頭文件的這個“標識”都應該是唯一的。標識的命名規則一般是頭文件名全大寫,前后加下劃線,并把文件名中的“.”也變成下劃線,如:

  stdio.h

  #ifndef _STDIO_H_

  #define _STDIO_H_

  ......

  #endif

  (BTW:預編譯有多很有用的功能。你會用預編譯嗎?)

  堆內存分配

  —————

  char*

  AllocStrFromHeap(int len)

  {

  char *pstr;

  if ( len <= 0 ) return NULL;

  return ( char* ) malloc( len );

  } 轉貼于 265考試網

  對于第一個函數,那塊pstr的內存在函數返回時就被系統釋放了。于是所返回的char*什么也沒有。而對于第二個函數,是從堆上分配內存,所以哪怕是程序退出時,也不釋放,所以第二個函數的返回的內存沒有問題,可以被使用。但一定要調用free釋放,不然就是Memory Leak!

  在堆上分配內存很容易造成內存泄漏,這是C/C++的最大的“克星”,如果你的程序要穩定,那么就不要出現Memory Leak。所以,我還是要在這里千叮嚀萬囑付,在使用malloc系統函數(包括calloc,realloc)時千萬要小心。

  記得有一個UNIX上的服務應用程序,大約有幾百的C文件編譯而成,運行測試良好,等使用時,每隔三個月系統就是down一次,搞得許多人焦頭爛額,查不出問題所在。只好,每隔兩個月人工手動重啟系統一次。出現這種問題就是Memery Leak在做怪了,在C/C++中這種問題總是會發生,所以你一定要小心。一個Rational的檢測工作——Purify,可以幫你測試你的程序有沒有內存泄漏。

  我保證,做過許多C/C++的工程的程序員,都會對malloc或是new有些感冒。當你什么時候在使用malloc和new時,有一種輕度的緊張和惶恐的感覺時,你就具備了這方面的修養了。

  對于malloc和free的操作有以下規則:

  1) 配對使用,有一個malloc,就應該有一個free。(C++中對應為new和delete)

  2) 盡量在同一層上使用,不要像上面那種,malloc在函數中,而free在函數外。最好在同一調用層上使用這兩個函數。

  3) malloc分配的內存一定要初始化。free后的指針一定要設置為NULL。注:雖然現在的操作系統(如:UNIX和Win2k/NT)都有進程內存跟蹤機制,也就是如果你

  有沒有釋放的內存,操作系統會幫你釋放。但操作系統依然不會釋放你程序中所有產生了Memory Leak的內存,所以,最好還是你自己來做這個工作。(有的時候不知不覺就出現Memory Leak了,而且在幾百萬行的代碼中找無異于海底撈針,Rational有一個工具叫Purify,可能很好的幫你檢查程序中的Memory Leak)

  9、變量的初始化

  接上一條,變量一定要被初始化再使用。C/C++編譯器在這個方面不會像J***A一樣幫你初始化,這一切都需要你自己來,如果你使用了沒有初始化的變量,結果未知。好的程序員從來都會在使用變量前初始化變量的。如:

  1) 對malloc分配的內存進行memset清零操作。(可以使用calloc分配一塊全零的內存)

  2) 對一些棧上分配的struct或數組進行初始化。(最好也是清零)不過話又說回來了,初始化也會造成系統運行時間有一定的開銷,所以,也不要對所有的變量做初始化,這個也沒有意義。好的程序員知道哪些變量需要初始化,哪些則不需要。

  如:以下這種情況,則不需要。

  char *pstr; /* 一個字符串 */

  pstr = ( char* ) malloc( 50 );

  if ( pstr == NULL ) exit(0);

  strcpy( pstr, "Hello Wrold" );

  strcpy( pstr, "Hello Wrold" );

  但如果是下面一種情況,最好進行內存初始化。(指針是一個危險的東西,一定要初始化 )

  char **pstr; /* 一個字符串數組 */

  pstr = ( char** ) malloc( 50 );

  if ( pstr == NULL ) exit(0);

  /* 讓數組中的指針都指向NULL */

  memset( pstr, 0, 50*sizeof(char*) );

  而對于全局變量,和靜態變量,一定要聲明時就初始化。因為你不知道它第一次會在哪里被使用。所以使用前初始這些變量是比較不現實的,一定要在聲明時就初始化它們。如:

  Links *plnk = NULL; /* 對于全局變量plnk初始化為NULL */

  10、h和c文件的使用

  H 文件和C文件怎么用呢?一般來說,H文件中是declare(聲明),C文件中是define(定義)。因為C文件要編譯成庫文件(Windows下是. obj/.lib,UNIX下是.o/.a),如果別人要使用你的函數,那么就要引用你的H文件,所以,H文件中一般是變量、宏定義、枚舉、結構和函數接口的聲明,就像一個接口說明文件一樣。而C文件則是實現細節。

  H文件和C文件最大的用處就是聲明和實現分開。這個特性應該是公認的了,但我仍然看到有些人喜歡把函數寫在H文件中,這種習慣很不好。(如果是C++話,對于其模板函數,在VC中只有把實現和聲明都寫在一個文件中,因為 VC不支持export關鍵字)。而且,如果在H文件中寫上函數的實現,你還得在makefile中把頭文件的依賴關系也加上去,這個就會讓你的 makefile很不規范。

  最后,有一個最需要注意的地方就是:帶初始化的全局變量不要放在H文件中!

  例如有一個處理錯誤信息的結構:

  char* errmsg[] = {

  /* 0 */ "No error",

  /* 1 */ "Open file error",

  /* 2 */ "Failed in sending/receiving a message",

  /* 3 */ "Bad arguments",

  /* 4 */ "Memeroy is not enough",

  /* 5 */ "Service is down; try later",

  /* 6 */ "Unknow information",

  /* 7 */ "A socket operation has failed",

  /* 8 */ "Permission denied",

  /* 9 */ "Bad configuration file format",

  /* 10 */ "Communication time out",

  ......

  ......

  };

  請不要把這個東西放在頭文件中,因為如果你的這個頭文件被5個函數庫(.lib或是.a)所用到,于是他就被鏈接在這5個.lib或.a中,而如果你的一個程序用到了這5個函數庫中的函數,并且這些函數都用到了這個出錯信息數組。那么這份信息將有5個副本存在于你的執行文件中。如果你的這個errmsg很大的話,而且你用到的函數庫更多的話,你的執行文件也會變得很大。

  正確的寫法應該把它寫到C文件中,然后在各個需要用到errmsg的C文件頭上加上 extern char* errmsg[]; 的外部聲明,讓編譯器在鏈接時才去管他,這樣一來,就只會有一個errmsg存在于執行文件中,而且,這樣做很利于封裝。

  我曾遇到過的最瘋狂的事,就是在我的目標文件中,這個errmsg一共有112個副本,執行文件有8M左右。當我把errmsg放到C文件中,并為一千多個 C文件加上了extern的聲明后,所有的函數庫文件尺寸都下降了20%左右,而我的執行文件只有5M了。一下子少了3M啊。

  [ 備注 ]

  有朋友對我說,這個只是一個特例,因為,如果errmsg在執行文件中存在多個副本時,可以加快程序運行速度,理由是errmsg的多個復本會讓系統的內存換頁降低,達到效率提升。像我們這里所說的errmsg只有一份,當某函數要用errmsg時,如果內存隔得比較遠,會產生換頁,反而效率不高。

  生副本導致執行文件尺寸變大,不僅增加了系統裝載時間,也會讓一個程序在內存中占更多的頁面。而對于errmsg這樣數據,一般來說,在系統運行時不會經常用到,所以還是產生的內存換頁也就不算頻繁。權衡之下,還是只有一份errmsg的效率高。即便是像logmsg這樣頻繁使用的的數據,操作系統的內存調度算法會讓這樣的頻繁使用的頁面常駐于內存,所以也就不會出現內存換頁問題了。

55480 主站蜘蛛池模板: 成都网站建设制作_高端网站设计公司「做网站送优化推广」 | 挤出机_橡胶挤出机_塑料挤出机_胶片冷却机-河北伟源橡塑设备有限公司 | 金刚网,金刚网窗纱,不锈钢网,金刚网厂家- 河北萨邦丝网制品有限公司 | 一体式钢筋扫描仪-楼板测厚仪-裂缝检测仪-泰仕特(北京) | 低温等离子清洗机(双气路进口)-嘉润万丰 | 精雕机-火花机-精雕机 cnc-高速精雕机-电火花机-广东鼎拓机械科技有限公司 | 广州迈驰新GMP兽药包装机首页_药品包装机_中药散剂包装机 | 微型气泵-真空-蠕动-水泵-厂家-深圳市品亚科技有限公司 | 福兰德PVC地板|PVC塑胶地板|PVC运动地板|PVC商用地板-中国弹性地板系统专业解决方案领先供应商! 福建成考网-福建成人高考网 | 雪花制冰机(实验室雪花制冰机)百科 | 河南道路标志牌_交通路标牌_交通标志牌厂家-郑州路畅交通 | 土壤养分检测仪|土壤水分|土壤紧实度测定仪|土壤墒情监测系统-土壤仪器网 | 创客匠人-让IP变现不走弯路 | 快速卷帘门_硬质快速卷帘门-西朗门业 | 绿叶|绿叶投资|健康产业_绿叶投资集团有限公司 | 超声波破碎仪-均质乳化机(供应杭州,上海,北京,广州,深圳,成都等地)-上海沪析实业有限公司 | 大_小鼠elisa试剂盒-植物_人Elisa试剂盒-PCR荧光定量试剂盒-上海一研生物科技有限公司 | 砂尘试验箱_淋雨试验房_冰水冲击试验箱_IPX9K淋雨试验箱_广州岳信试验设备有限公司 | 压缩空气检测_气体_水质找上海京工-服务专业、价格合理 | 储能预警-储能消防系统-电池舱自动灭火装置-四川千页科技股份有限公司官网 | 列管冷凝器,刮板蒸发器,外盘管反应釜厂家-无锡曼旺化工设备有限公司 | 陕西安闸机-伸缩门-车牌识别-广告道闸——捷申达门业科技 | 土壤养分检测仪|土壤水分|土壤紧实度测定仪|土壤墒情监测系统-土壤仪器网 | 空气净化器租赁,空气净化器出租,全国直租_奥司汀净化器租赁 | 德国EA可编程直流电源_电子负载,中国台湾固纬直流电源_交流电源-苏州展文电子科技有限公司 | 超声波焊接机,振动摩擦焊接机,激光塑料焊接机,超声波焊接模具工装-德召尼克(常州)焊接科技有限公司 | 焊锡丝|焊锡条|无铅锡条|无铅锡丝|无铅焊锡线|低温锡膏-深圳市川崎锡业科技有限公司 | 短信营销平台_短信群发平台_106短信发送平台-河南路尚 | 手术室净化厂家_成都实验室装修公司_无尘车间施工单位_洁净室工程建设团队-四川华锐16年行业经验 | 电动卫生级调节阀,电动防爆球阀,电动软密封蝶阀,气动高压球阀,气动对夹蝶阀,气动V型调节球阀-上海川沪阀门有限公司 | 中央空调温控器_风机盘管温控器_智能_液晶_三速开关面板-中央空调温控器厂家 | 深圳标识制作公司-标识标牌厂家-深圳广告标识制作-玟璟广告-深圳市玟璟广告有限公司 | 数年网路-免费在线工具您的在线工具箱-shuyear.com | 杭州可当科技有限公司—流量卡_随身WiFi_AI摄像头一站式解决方案 | 聚合氯化铝-碱式氯化铝-聚合硫酸铁-聚氯化铝铁生产厂家多少钱一吨-聚丙烯酰胺价格_河南浩博净水材料有限公司 | 在线浊度仪_悬浮物污泥浓度计_超声波泥位计_污泥界面仪_泥水界面仪-无锡蓝拓仪表科技有限公司 | 注塑机-压铸机-塑料注塑机-卧式注塑机-高速注塑机-单缸注塑机厂家-广东联升精密智能装备科技有限公司 | 深圳网站建设-高端企业网站开发-定制网页设计制作公司 | 茅茅虫AI论文写作助手-免费AIGC论文查重_写毕业论文降重 | 氧化锆纤维_1800度高温退火炉_1800度高温烧结炉-南京理工宇龙新材料股份有限公司 | 净化工程_无尘车间_无尘车间装修-广州科凌净化工程有限公司 |