C語言軟件編程經驗交流_第1頁
C語言軟件編程經驗交流_第2頁
C語言軟件編程經驗交流_第3頁
C語言軟件編程經驗交流_第4頁
C語言軟件編程經驗交流_第5頁
已閱讀5頁,還剩63頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

C語言軟件編程之經驗交流1.這次報告比較局限于C語言,不會講太多其他高級語言比方C++,JAVA,PYTHON等等,剛進實驗室的學生我的建議是先學好C語言,掌握工程開發中軟件的開發目的,開發流程,測試流程等。注意,做這個報告的目的是希望大家能夠開發出高效的C程序,而不是讓大家開發出復雜高難度高技巧的C程序。報告目的2.提綱一、C語言根底二、內存管理三、常用技巧四、調試五、例如3.開發軟件工欲善其事,必先利其器------?論語?牢牢打好根底,緊緊抓住核心,真正實現目的-----深入學習科學開展觀編輯軟件:VC++6.0,VS20XX編程輔助軟件:msdn功能性輔助軟件:vcassistant,numegaboundschecker, intelvtune,sourceinsight推薦的資料:?高質量C/C++編程指南(林銳)?、?Windows核心編程?、?linux高級程序設計?4.一、C語言根底在C語言中使用的詞匯分為六類:標識符,關鍵字,運算符,分隔符,常量,注釋符。1.1.1C語言詞匯5.標識符只能是字母、數字、下劃線組成的字符串,并且其第一個字符必須是字母或下劃線。

以下標識符是合法的:a,x,_3x,BOOK_1,sum5

以下標識符是非法的:3s以數字開頭; s*T出現非法字符*;-3x以減號開頭;

〔1〕標識符一、C語言根底6.在使用標識符時注意以下幾點:標準C不限制標識符的長度,但它受各種版本的C語言編譯系統限制,同時也受到具體機器的限制;在標識符中,大小寫是有區別的。例如BOOK和book是兩個不同的標識符;標識符雖然可由程序員隨意定義,但標識符是用于標識某個量的符號。因此,命名應盡量有相應的意義,以便閱讀理解,作到“顧名思義〞。intImgWidth;

〔1〕標識符一、C語言根底7.1、匈牙利命名法:開頭字母用變量類型的縮寫,其余局部用變量的英文或英文的縮寫,要求單詞第一個字母大寫。 intiMyAge;“i〞是int類型的縮寫;

charcMyName[10];“c〞是char類型的縮寫;

floatfManHeight;“f〞是float類型的縮寫;2、駝峰規那么: 又叫小駝峰式命名法。

第一個單詞首字母小寫,后面其他單詞首字母大寫。 intmyAge;

charmyName[10];

floatmanHeight;3.帕斯卡命名法: 又叫大駝峰式命名法。每個單詞的第一個字母都大寫。

intMyAge;

charMyName[10];

floatManHeight;一、C語言根底8.關鍵字是由C語言規定的具有特定意義的字符串,通常也稱為保存字。用戶定義的標識符不應與關鍵字相同。C語言的關鍵字分為以下幾類:〔2〕關鍵字一、C語言根底類型說明符

用于定義、說明變量、函數或其它數據結構的類型。如char,short,int,double等語句定義符

用于表示一個語句的功能。如for,if,else,while,switch等。預處理命令字

用于表示一個預處理命令。如#define#pragma等。9.C語言中運算符與變量,函數一起組成表達式,表示各種運算功能。運算符由一個或多個字符組成,如>,<=,&&等。〔3〕運算符〔4〕分隔符在C語言中采用的分隔符有逗號和空格兩種。一、C語言根底10.〔5〕常量C語言中使用的常量可分為數字常量、字符常量、字符串常量、符號常量、轉義字符等多種。比方char*p=“helloworld〞;C語言中的常量是不接受程序修改的固定值。〔6〕注釋符C語言的注釋符是以“/*〞開頭并以“*/〞結尾的串,C++中使用“//〞注釋所在行。一、C語言根底11.什么是字節對齊,為什么要字節對齊?1.1.2字節對齊一、C語言根底12.〔1〕什么是字節對齊?現代計算機中內存空間都是按照byte劃分的,從理論上講對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經常在特定的內存地址訪問,這就需要各類型數據按照一定的規那么在空間上排列,而不是順序的一個接一個的排放,這就是對齊。一、C語言根底13.〔2〕為什么要字節對齊?對齊的作用和原因:各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數據只能從某些特定地址開始存取。其他平臺可能沒有這種情況,但是最常見的是如果不按照適合其平臺的要求對數據存放進行對齊,會在存取效率上帶來損失。比方有些平臺每次讀都是從偶地址開始,如果一個int型〔假設為32位〕如果存放在偶地址開始的地方,那么一個讀周期就可以讀出,而如果存放在奇地址開始的地方,就可能會需要2個讀周期,并對兩次讀出的結果的上下字節進行拼湊才能得到該int數據。一、C語言根底14.〔3〕大小端〔例程〕在計算機系統中,我們是以字節為單位的,每個地址單元都對應著一個字節,一個字節為8bit。對于位數大于8位的處理器,由于存放器寬度大于一個字節,那么必然存在著一個如何將多個字節安排的問題。所謂的大端模式,是指數據的低位保存在內存的高地址中,而數據的高位,保存在內存的低地址中;所謂的小端模式,是指數據的低位保存在內存的低地址中,而數據的高位保存在內存的高地址中一、C語言根底15.〔3〕大小端〔例程〕寫一個C函數,假設處理器是Big_endian的,那么返回0;假設是Little_endian的,那么返回1intcheckCPU(){ unionw { inta; charb; }c; c.a=1; return(c.b==1);}一、C語言根底16.〔3〕大小端〔例程〕采用Little-endian模式的CPU對操作數的存放方式是從低字節到高字節,而Big-endian模式對操作數的存放方式是從高字節到低字節序是所有成員都從低地址開始存放。聯合體union的存放順序是所有成員都從低地址開始存放。一、C語言根底17.//作者版權版本說明,頭文件聲明,全局變量,函數聲明,預處理塊#include<stdlib.h>#include〞global.h〞voidoutput();//子函數聲明intmain(intargc,char*argv[]){ inti,j; unsignedchar*data;//定義局部變量 //分配數據空間,分配在堆上 data=(unsignedchar*)malloc(1000*sizeof(unsignedchar)); for(i…){} //調用子函數 output(); //釋放分配空間 free(data);data=NULL;}voidoutput(){…}一、C語言根底18.#ifndefGRAPHICS_H(作用:防止graphics.h被重復引用)

#defineGRAPHICS_H

#include....(作用:引用標準庫的頭文件)

#include...(作用:引用非標準庫的頭文件)

voidFunction1(...);(作用:全局函數聲明)

classBox(作用:類結構聲明)

{};

#endif1.2.1頭文件一、C語言根底19.在頭文件中,用ifndef/define/endif結構產生預處理塊,用#include格式來引用庫的頭文件。頭文件一般由三局部內容組成:1.2.1頭文件頭文件開頭處的版權和版本聲明;預處理塊;函數和類結構聲明等。一、C語言根底20.頭文件的主要作用在于調用庫功能,對各個被調用函數給出一個描述,其本身不包含程序的邏輯實現代碼,它只起描述性作用,告訴應用程序通過相應途徑尋找相應功能函數的真正邏輯實現代碼。用戶程序只需要按照頭文件中的接口聲明來調用庫功能,編譯器會從庫中提取相應的代碼。1.2.1頭文件一、C語言根底21.注意:1)在.h文件中聲明的函數,如果在其對應的.c文件中有定義,那么我們在聲明這個函數時,不使用extern修飾符,如果反之,那么必須顯示使用extern修飾符;2)不要在.h文件中編寫實現代碼,不要#include“.c〞文件。1.2.1頭文件一、C語言根底22.所有全局變量盡量以g_開頭,并且盡可能聲明成static類型;盡量杜絕跨文件訪問全局變量.如果確實需要在多個文件內訪問同一變量,應該由該變量定義所在文件內提供GET/PUT函數實現;全局變量必須要有一個初始值,全局變量盡量放在一個專門的函數內初始化;如調用全局變量的函數少于三個,考慮改為局部變量實現。1.2.2謹慎使用全局變量一、C語言根底23.在實際的軟件工程中,每個人負責的可能只是一個模塊,對全局變量的使用沒有小程序那樣簡單,在使用全局變量的時候更要謹慎,跨模塊調用的全局變量使用時都需要申請,而且定義必須明確。1.2.2謹慎使用全局變量一、C語言根底24.voidmain(intargc,char*argv[])1.2.3main函數一、C語言根底命令行界面的程序,通常都需要輸入命令行參數幫助程序執行。假定有一個可執行程序名為test.exe。運行該程序的的命令行如下:test.exe帶命令行參數是同一行中的附加項:test.exe–cTEST其中–c和TEST就是命令行參數。C程序通過使用main()的參數來讀取這些附加參數。25.main(intargc,char*argv[])這個函數中兩個參數的意義:argc記錄的是命令行中輸入參數的數目;argv是一個擁有argc個元素的字符串數組,每個元素保存一個命令行中輸入的參數。1.2.3main函數一、C語言根底26.

#include<stdio.h> intmain(intargc,char*argv[]) { inti; for(i=0;i<argc;i++) { printf("Argument%dis%s.\n",i,argv[i]); } return0; }1.2.3main函數一、C語言根底下面的程序演示argc和argv的使用:27.Argument0ishello.exe.Argument1isa.Argument2isb.Argument3isc.Argument4isd.Argument5ise.1.2.3main函數一、C語言根底運行結果:假設上述代碼編譯為hello.exe,那么運行:hello.exeabcde28.1.2.3main函數一、C語言根底在這個例子中,argc的值為6,命令行一共輸入了六個參數:“hello.exe〞、“a〞、“b〞、“c〞、“d〞、“e〞對應程序輸入為:argv[0]:repeat.exe,argv[1]:a,argv[2]:b,argv[3]:c,argv[4]:dargv[5]:e需要注意的是假設輸入參數作為數值使用時,使用atoiatof進行字符轉換看例程29.一、C語言根底1.3代碼編寫標準從書寫清晰,便于閱讀,理解,維護的角度出發,在書寫程序時應遵循以下規那么:一個說明或一個語句占一行。if,for,while,do占一行,執行語句放后面并且使用大括號,多用對齊。用{}括起來的局部,通常表示了程序的某一層次結構。{}一般與該結構語句的第一個字母對齊,并單獨占一行。低一層次的語句或說明可比高一層次的語句或說明縮進假設干格后書寫。以便看起來更加清晰,增加程序的可讀性。在編程時應力求遵循這些規那么,以養成良好的編程風格。多寫注釋,合理的使用注釋可以讓你的程序可讀性更高。30.一、C語言根底另外一些編程風格說明:程序塊要采用縮進風格編寫,縮進少使用空格鍵;對齊多使用TAB鍵,少使用空格鍵;逗號、分號只在后面加空格。inta,b,c;比較操作符,賦值操作符“=〞,“+=〞,算術操作符“+〞,“%〞,邏輯操作符“&&〞,“&〞,位域操作符“<<〞,“^〞等雙目操作符的前后加空格;31.一、C語言根底另外一些編程風格說明:“!〞,“~〞,“++〞,“--〞,“&〞〔地址運算符〕等單目操作符前后不加空格。“->〞,“.〞前后不加空格。p->id=pid;//“->〞指針前后不加空格if、for、while、switch等與后面的括號間應加空格,使if等關鍵字更為突出、明顯。if(a>=b&&c>d)32.一、C語言根底33.一、C語言根底1.4命名規那么使用匈牙利命名法,標識符應直觀意思明確盡量使用縮寫,如intiImgWidth;不要使用大小寫來區分變量,如intx,X;局部變量不要與全局變量同名;常量使用大寫字母,合理使用前綴,靜態變量加前綴s_,全局變量加前綴g_。34.一、C語言根底1.5表達式注意優先級的的上下以及結合順序,多使用括號確定優先級35.一、C語言根底1.5表達式注意if常用的條件判斷情況:布爾變量if〔flag〕if〔!flag〕整型變量if〔flag==0〕if〔flag!=0〕浮點變量if〔abs〔x-0〕<1e-5〕指針變量if〔p==NULL〕if〔p!=NULL〕if語句36.一、C語言根底1.5表達式注意以下幾點:多重循環中,盡量將循環少的放在外層循環for〔i=0;i<N;i++〕,循環執行N次,最大執行到i=N-1,i最后執行完等于Nswitch的每個case都加上break,最后加上default盡量少用goto循環語句37.從靜態存儲區域分配,在程序編譯的時候就已經分配好,整個運行期都存在。如全局變量和static變量。從棧上創立,從函數創立開始存在,函數結束就釋放,效率高,但是分配大小有限。如函數內部變量。從堆上分配,也稱動態內存分配。使用malloc分配,需要手動free釋放。使用靈活,容易出問題。C語言中內存分配區域:二、內存管理38.二、內存管理2.1常見內存錯誤沒有分配直接使用或者分配未成功卻使用了它;沒有初始化或者歸零就直接使用〔分配內存后系統默認值不一定是0〕;使用時內存訪問越界,使用完忘記釋放內存,造成內存泄漏;對已分配內存的指針進行賦值操作,原來分配內存區域喪失,內存泄漏;釋放了內存卻繼續使用,指針在釋放后并不是變為NULL,仍然指向原來地址,成為“野指針〞。39.二、內存管理2.2指針與數組數組在棧上和靜態存儲區域創立,其地址與容量分配后不可改變,但內容可以改變;指針的特征是“可變〞,用于分配動態內存區域;不能直接對數組名進行復制和比較,使用strcpy和strcmp;指針存儲的是動態內存區域的地址,可以直接傳遞地址,當對兩塊動態內存區域復制或比較時使用memcpy和memcmp;數組的大小,需要加上最后面的‘\0’,可以使用sizeof獲得;指針使用sizeof獲得的是指針變量的字節數;需要注意的是當數組作為函數參數傳遞時,自動退化為該類型的指針。40.二、內存管理2.2指針與數組例子:41.二、內存管理2.3指針指針的本質是地址,指針變量本身作為普通存放器變量被存儲,特別是該存放器地址內存儲的是另一個存放器地址,該存放器地址內存儲的數據是指針指向的數據。棧maininti=200;char*p;0x123456假設已給p分配空間0x123456p=0x123456i=2000x1234560x123452100*p=1000x2021120x202116&p=0x202116&i=0x202120200棧42.二、內存管理2.3指針malloc在堆上分配動態內存區域,需要指定分配區域的大小,以字節作為單位。p=(char*)malloc(1*sizeof(char)); //分配到0x123456,存儲在棧地址0x202116的內存地址中 *p=100;//修改0x123456中數值為100 //free將分配的動態內存區域釋放 free(p); //雖然0x123456該地址被標志為已釋放,但是p內存儲的仍然是0x123456,p成為野指針 p=NULL; //將0x202116內數據改為0x00,該地址不可訪問malloc與free:43.二、內存管理當子函數中使用指針時,子函數執行結束指針沒有free掉,此時指針變量釋放了,不代表它所指向的內存自動釋放了。當內存被釋放時,不代表指針不存在了或者指針成為NULL指針。需要查找程序內存泄漏。2.3指針需要注意的幾點:44.三、常用技巧3.1宏的使用#defineceil_div(x,y)(x+y-1)/y宏執行的是簡單的替換作用,需要注意由操作符優先級引起的問題,多加括號。那么a=ceil_div(b&c,sizeof(int));將被轉化為:a=(b&c

+sizeof(int)-1)/sizeof(int);由于+/-的優先級高于&的優先級,那么上面式子等同于:a=(b&(c+sizeof(int)-1))/sizeof(int);為了防止這種情況發生,應當多寫幾個括號:#defineceil_div(x,y)(((x)+(y)-1)/(y))45.三、常用技巧3.1宏的使用函數變宏每行代碼最后都加行連接符“\〞,即使是空行也要加“\〞,最后一行代碼后面不需要加“\〞,每行“\〞最后不能有多余字符或者空格,返回的是最后一條語句的執行結果。可以在宏函數內定義變量,可以使用if等語句,可以在宏內調用其他宏,可以使用指針。函數變宏可以加快程序運行速度。看例子46.三、常用技巧3.2運行時間測量程序運行過程中,我們經常需要統計程序運行時間。下面給出例如:#include<time.h>main(){ clock_tbegin,end; begin=clock(); end =clock(); double

duration; duration=(double)(end-begin)/CLOCKS_PER_SEC;

printf(“Timeis%2.1fseconds\n",duration); //#defineCLOCKS_PER_SEC1000 //事實上end–begin獲得的是毫秒計數}47.三、常用技巧3.2運行時間測量Time()函數是獲得當前系統時間用的,一般不用于計時。當程序運行時間太短時,可以使用屢次執行的方法來獲得。可以使用更精確的運行時間計數函數:“QueryPerformanceCounter()〞“QueryPerformanceFrequency()〞48.三、常用技巧隨機數生成:#include<stdlib.h>#include<stdio.h>#include<time.h>voidmain(void){ inti;/*Seedtherandom-numbergeneratorwithcurrenttimesothat*thenumberswillbedifferenteverytimewerun.*/ srand((unsigned)time(NULL));/*Display10numbers.*/ for(i=0;i<10;i++) printf("%6d\n",rand());}Srand是產生偽隨機序列的種子,種子一樣產生的偽隨機序列一樣。RAND_MAX=0x7fffffffj=(int)(n*rand()/(RAND_MAX+1.0))產生一個0到n之間的隨機數49.三、常用技巧3.3文件操作文件的翻開與關閉文件在進行讀寫操作之前要先翻開,使用完畢要關閉。翻開文件實際上是建立文件的各種有關信息,并使文件指針指向該文件,以便進行其它操作。關閉文件那么斷開指針與文件之間的聯系,也就禁止再對該文進行操作。在C語言中,文件操作都是由庫函數來完成的。 fp=fopen(“filename〞,“r〞);50.三、常用技巧對于文件使用方式有以下幾點說明:文件使用方式由r,w,a,b,t,+六個字符拼成,各字符的含義是:r(read):讀w(write):寫a(append):追加b(binary):二進制文件+:讀和寫凡用“r〞翻開一個文件時,該文件必須已經存在,且只能從該文件讀出。用“w〞翻開的文件只能向該文件寫入。假設翻開的文件不存在,那么以指定的文件名建立該文件,假設翻開的文件已經存在,那么將該文件刪去,重建一個新文件。51.三、常用技巧if((fp=fopen(“readme.txt","rb")==NULL)

{

printf("\nerroronopenc:\\hzk16file!");

exit(1);

}假設要向一個已存在的文件追加新的信息,只能用“a〞方式翻開文件。但此時該文件必須是存在的,否那么將會出錯。在翻開一個文件時,如果出錯,fopen將返回一個空指針值NULL。在程序中可以用這一信息來判別是否完成翻開文件的工作,并作相應的處理。52.三、常用技巧文件的讀寫對文件的讀和寫是最常用的文件操作。在C語言中提供了多種文件讀寫的函數:字符讀寫函數:fgetc和fputc字符串讀寫函數:fgets和fputs數據塊讀寫函數:fread和fwrite格式化讀寫函數:fscanf和fprinf行操作。53.三、常用技巧文件的讀寫在文件內部有一個位置指針,用來指向文件的當前讀寫字節。在文件翻開時,該指針總是指向文件的第一個字節。使用fgetc函數后,該位置指針將向后移動一個字節。應注意文件指針和文件內部的位置指針不是一回事。文件指針是指向整個文件的,文件內部的位置指針用以指示文件內部的當前讀寫位置,每讀寫一次,該指針系統自動向后移動。54.三、常用技巧計算文件長度的程序例如longfilesize(FILE*stream){longcurpos,length;curpos=ftell(stream);fseek(stream,0L,SEEK_END);length=ftell(stream);fseek(stream,curpos,SEEK_SET);returnlength;}進行二進制文件讀寫時,翻開方式后面加“b〞55.四、調試編程出現error時,從第一個error處開始解決錯誤,可能是很小的書寫錯誤引起的。warning也需要關注,有時候會導致程序運行錯誤發生。程序出現BUG時,單步跟蹤,查看變量,查看內存,查看棧調用,可以邊編輯邊跟蹤。參加適宜的斷點,使用條件斷點。程序調試結束后需要查找內存泄露,標準代碼書寫。使用assert,只有條件滿足才繼續向下執行,在release下不會編譯該語句。程序編寫完成不一定是完全正確的,需要進行測試并進行跟蹤調試。56.四、調試4.1條件斷點我們在調試的時候希望程序在某個斷點處只有在滿足一定的條件下中斷,在不滿足條件的時候正常運行,可以為程序調試帶來極大的便利。例如57.四、調試4.2內存泄漏查找養成好的代碼寫作標準,掌握內存管理概念,減少不標準代碼內存泄漏可能性。是否內存泄露:運行可執行文件,使用任務管理器查看內存占用情況是否一直增加。比較簡單但是顯示不一定精確。使用NumegaBounderChecker軟件查找,程序中參加exit(0)強制中斷,Debug至該代碼行程序異常中斷時查看內存泄露報告。例如58.四、調試4.3watch跟蹤調試時多使用watch窗口,在watch窗口內可以進行有限運算,注意watch運算帶來的影響。例如59.四、調試4.4C程序優化首先要確定優化目標,然后尋找優化方法。查找程序運行瓶頸,使用IntelVtune查看各局部運行時間,一步步進行優化。現在CPU,GPU開展方向都是多核,并行計算越來越方便,為優化提供了更多解決方案。任務級并行,使用多線程發揮多核優勢。指令級并行,使用MMX,SSE,SSE2等指令集。參看Vtune使用指南60.五、例如5.1軟件設計算法思想,思路清楚,注意細節質量控制,代碼高效,風格良好測試調試,測試全面,調試認真軟件設計過程關鍵局部:在編寫軟件程序之前,首先要明確你要解決的問題,軟件只是思想的實現,不能通過編程來獲得思想。所以在編寫之前就需要對問題有透徹的理解,對解決問題的方法有清晰的思路,要考慮到可能遇到的所有問題,同時要考慮到軟件的可靠性穩定性等。61.五、例如5.1軟件設計在編寫軟件程序之前,首先要明確你要解決的問題,軟件只是思想的實現,不能通過編程來獲得思想。所以在編寫之前就需要對問題有透徹的理解,對解決問題的方法有清晰的思路,要考慮到可能

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論