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

首頁 > 學院 > 開發設計 > 正文

C/C++編程新手錯誤語錄(續二)

2019-11-17 05:03:39
字體:
來源:轉載
供稿:網友
前文回顧:C/C++編程新手錯誤語錄  錯誤語錄(續一)(13)“整型變量僅僅意味著一個整數”
  當我們還是一個新手,看整型就是整數;

  當我們成為高手,看什么都是整型。

  整型,在所有C/C++基本數據類型中最富有藝術魅力和奇幻色彩。

  我們從某聞名論壇的一篇帖子開始一窺整型的奧妙。

  問:Vxworks操作系統啟動一個任務的函數是taskSpawn(char* name, int PRiority, int options, int stacksize, FUNCPTR function, int arg1,.. , int arg10),它只接受整型參數,我該怎么辦才能給它傳一個結構體(在32位PowerPC平臺下)?

  答:可以傳入結構體的指針,在32位PowerPC平臺下,指針本質上就是一個32位整數,在函數體內將整型強制轉化為結構體指針就可訪問結構體的每一個元素。

  如:
//啟動任務1
taskSpawn(“task1”, 180, NULL, 10000, Task1Fun, &pStrUCtAr,0,0,0,0,0,0,0,0,0);
//task1函數
Task1Fun ( int arg1 )
{
struct_x * pStructx = (struct_x *) arg1; //將整型強制轉化為結構體指針

}
  在此提出“泛整型”的概念,(unsigned)char、(unsigned)short int、(unsigned)int、(unsigned)long int等都屬于這個范疇,指針必然屬于“泛整型”的范圍。用指針的高超境界,也為將其看做一個“泛整型”。

  看看軟件的具體設計文檔,其數據結構定義部分經常看到“INT8、UINT8、INT16、UINT16、INT32、UINT32、INT64、UINT64”或“BYTE、Word、DWORD”等數據類型,它們在本質上都是(unsigned)char、(unsigned)short int、(unsigned)int、(unsigned)long int宏定義的結果,都屬于“泛整型”。所以,“泛整型”的概念真實地體現在日常的軟件設計當中。

更多文章 更多內容請看C/C++技術專題  java編程開發手冊專題,或
  正因為各種指針類型在本質上都是“泛整型”,因此它們可以互相轉化:
int a, b;
memset( (char*) &a, (char*) &b, sizeof(int) );
  等價于:
int a, b;
a = b;

  從來沒有人會用memset( (char*) &a, (char*) &b, sizeof(int) )來代替a = b,這里只是為了說明問題。下面的代碼則經常用到:
int *p = (int *) malloc(100*sizeof(int));

memset ( p, 0, 100*sizeof(int) ); //將申請的內存空間清0
  我們看memset的函數原型為:
void * memset ( void * buffer, int c, size_t num );
  實際上它接受的第一個參數是無類型指針,在memset函數體內,其它任意類型的指針都向void *轉化了。類似的內存操作函數memcpy所接受的源和目的內存地址也是無類型指針。

  char *轉化為int *后的值雖然不變(還是那個地址),但是其++、--等操作的含義卻發生了變化,這也是要注重的。
char *p;
++p;
  與
char *p;
++(int *)p;
  的結果是不一樣的,前者的p值加了1,而后者的則增加了sizeof(int)。

  下面來剝Windows程序設計中消息傳遞函數兩個參數的皮,看看它們究竟是什么:
typedef UINT WPARAM;
typedef LONG LPARAM;
  原來,WPARAM和LPARAM其實都屬于“泛整型”,所以不要報怨消息處理函數只能接受“泛整型”。實際上,從指針的角度上來講,在C/C++中,可以獲得任何類型實例(變量、結構、類)的指針,所以Windows的消息處理函數實際上可以接受一切類型的參數。

  驚天動地一句話:“泛整型”可表征一切。

更多文章 更多內容請看C/C++技術專題  Java編程開發手冊專題,或
(14)“值傳遞一定不會改變參數”

  理論而言,值傳遞的確不會改變參數的內容。但是,某年某月的某一天,隔壁Office的碩士mm寫了這么一段程序,參數的值卻被改變了:
int n = 9;
char a[10];
example ( n, a ); //調用函數example(int n,char *pStr)
printf (“%d”, n );  //輸出結果不是9
  大概整個office的人都被搞懵了,都說編譯器瞎搞,有問題。找到筆者,筆者憑借以往的經常,一眼就看出來不是什么編譯器出錯,而是在函數example內對字符串a的訪問越界!

  當在函數example內對a的訪問越界后,再進行寫操作時,就有可能操作到了n所在的內存空間,于是改變了n的值。

  給出這個語錄,并非為了推翻“值傳遞不會改變參數”的結論,而是為了從側面證實在C/C++語言中,數組越界是多么危險的錯誤!

  下面的兩個函數有明顯的數組越界:
void example1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
void example 2(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
  而這個函數的越界就不這么明顯:
void example3()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
  其實,這個函數危險到了極點。因為對于strcpy函數而言,拷貝的時候要碰到’/0’才結束,str1并沒有被賦予結束符,因而你根本就不知道strcpy( string, str1 )的結果究竟會是拷貝多大一片內存!

  遺憾的是,C/C++永遠不會在編譯和連接階段提示數組越界,它只會在運行階段導致程序的崩潰。

  數組越界,是大多數C/C++編程新手常犯的錯誤,而它又具有極大的隱蔽性,新手們一定要非凡注重。

更多文章 更多內容請看C/C++技術專題  Java編程開發手冊專題,或
(15)“C不高級,學C++、JAVA、C#才夠味”

  也許譚浩強老師的C語言教材是絕大多數高校學生學習的第一門編程課程,所以在許多學生的心目中,覺得C是一種入門級的語言,他們舍棄基礎而追逐花哨的Visual XXX、Java、aspphp、.net,他們以為這樣做“賺大了”。


  非也!

  C是一種多么富有魅力的語言!在今時的絕對多數底層開發中,仍然幾乎被C完全壟斷。這些領域包括操作系統、嵌入式系統、數字信號處理等。舍棄C的經濟基礎搭.net的高層建筑實在是危險。

  我們總是以為自己把握了C,那么請寫一個strcpy的標準函數。您的答案若是:
void strcpy( char *strDest, char *strSrc )
{
  while( (*strDest++ = * strSrc++) != ‘/0’ );
}
  很遺憾,您的程序只能拿到E。看看拿A的strcpy:
char * strcpy( char *strDest, const char *strSrc )
{
 assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
 while( (*strDest++ = * strSrc++) != ‘/0’ );
return address;
}
  這個程序考慮了什么?

  (1)程序要強大:為了實現鏈式操作,將目的地址返回,函數返回類型改為char *

  (2)程序要可讀:源字符串指針參數加const限制,表明為輸入參數

  (3)程序要健壯:驗證strDest和strSrc非空

  假如這三點中您只考慮到0點或1點,那么請回家好好修煉一下C。因為這個最簡單的strcpy已驗證出您的C語言基礎只能叫做“入門”。

  再寫個簡單的strlen,這么寫就好了:
int strlen( const char *str ) //輸入參數為const
{
assert( strt != NULL ); //斷言字符串地址非0
int len;
while( (*str++) != '/0' )
{
len++;
}
return len;
}
  由此可見,寫好這些簡單的函數也需要深厚的基本功,永遠不要放棄對基本功的培養。

更多文章 更多內容請看C/C++技術專題  Java編程開發手冊專題,或
(16)“語言學得越多越好”

  許多的初學者都經歷過這樣的一個階段,面對大量的編程語言和開發環境,他們倆感到難以取舍,不知道自己究竟應該學習什么。于是他們什么都學,今天看一下Visual Basic,明天看學一下C++,后天在書點看到了本Java便心血來潮買回來翻翻,大后天又發現必須學.net了。他們很痛苦,什么都在看,結果什么都沒學會,忙忙碌碌而收獲甚微。

  我們真的沒有必要在什么語言都不甚精通的情況下亂看一氣。認準了一種真正語言就應該堅持不懈地努力。因為任何一門語言的把握都非一朝一夕一事,筆者從六年前開始接觸C++,直到現在,每一階段仍有新的啟發,在項目開發的過程中也不斷有新的收獲。今日我還是絕對不敢宣稱自己“精通”這門語言。

  許多剛畢業的大學生,動不動就在簡歷上寫上自己精通一堆語言。與之相反,大多數優秀的工程師都不敢這么寫。也許,研究越深,便越敢自身的無知。

  在下認為,一個成熟的語言體系應該是:
  程序員的語言體系 = 一種匯編 + C + 一種面向對象(C++、JAVA、C#等)

  假如還要加,那就加一種解釋型語言,perl或tcl(也許其它)。

  語言具有極大的相似性,從C++過渡到JAVA只需要很短的一段時間。各種語言的發展歷史也體現了編程思想的發展史。我們學習一種語言,語法也許并不是最重要的,最重要的是蘊藏在語法外表下的深層特性和設計用意。

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 砀山县| 鄂伦春自治旗| 班玛县| 乐至县| 临海市| 宁都县| 桐乡市| 陇南市| 汽车| 枝江市| 北碚区| 沁阳市| 太原市| 银川市| 施甸县| 河曲县| 南宁市| 若羌县| 灯塔市| 罗源县| 宾阳县| 金乡县| 浦北县| 五指山市| 拜城县| 青铜峡市| 庆城县| 南丰县| 红原县| 定边县| 宁强县| 龙门县| 淮安市| 察哈| 莱州市| 湘阴县| 祥云县| 米易县| 龙游县| 长宁区| 泽库县|