指針是C語(yǔ)言的靈魂,我們經(jīng)常聽到這樣的說法,當(dāng)我們初學(xué)C語(yǔ)言的時(shí)候,似乎覺得也沒有什么,但是當(dāng)你越來(lái)越深入的了解它,你就會(huì)發(fā)現(xiàn)C語(yǔ)言的強(qiáng)大有時(shí)甚至超乎你的想象。C語(yǔ)言作為一種相對(duì)較為底層的語(yǔ)言,在某些方面有著不可替代的優(yōu)勢(shì)。因此,要學(xué)好C語(yǔ)言,要深入,要精通。 C語(yǔ)言之回調(diào)函數(shù) 先來(lái)看下函數(shù)指針的的基礎(chǔ)知識(shí),函數(shù)指針,顧名思義,就是指向函數(shù)的指針,聲明方法如下: int func(int); //函數(shù)原型 int (*pfunc)(int) = & func; //創(chuàng)建函數(shù)指針pfunc,并指向函數(shù)func 這里的&操作符可有可無(wú),因?yàn)楹瘮?shù)名本身就是一個(gè)地址。 回調(diào)函數(shù)是一個(gè)程序員不能顯式調(diào)用的函數(shù);通過將回調(diào)函數(shù)的地址傳給調(diào)用者從而實(shí)現(xiàn)調(diào)用。在我們想通過一個(gè)統(tǒng)一接口實(shí)現(xiàn)不同的內(nèi)容時(shí),用回調(diào)函數(shù)非常合適。 例如:有如下用于不同設(shè)備的顯示函數(shù) Void A_show(); Void B_show(); Void C_show(); Void show(void (*ptr)()); 使用時(shí)我們就可以將函數(shù)作為參數(shù) show(A_show); 再舉一個(gè)經(jīng)典的例子,實(shí)現(xiàn)在一個(gè)單鏈表中查找一個(gè)值。 Node * Search_list(Node *node,int const value) { While(node!=NULL){ if(node->value == value) break; node = node->link; } return node; } 這個(gè)函數(shù)只適用于值為整形的鏈表,因?yàn)関alue的值為int型,如果此時(shí)你需要在一個(gè)字符串鏈表中查找,需要編寫另外的函數(shù)來(lái)實(shí)現(xiàn)。這時(shí)就用到了回調(diào)函數(shù),使查找函數(shù)與類型無(wú)關(guān),這樣就能用于任何類型的值的鏈表。 Node * Search_list(Node *node,void const value, int (*compare)(void const * ,void const *)) { While(node!=NULL){ if(compare(&node->value,value)==0) break; node = node->link; } return node; } int compare_ints(void const *a, void const *b) { if(*(int*)a == *(int *)b) return 0; else return 1; } 我們?cè)谑褂肧earch_list函數(shù)時(shí),你已經(jīng)知道要查找數(shù)據(jù)的數(shù)據(jù)類型了。用法如下: Desired_node = Search_list(root, &desired_value,compare_ints); 那如果你要在一個(gè)字符串鏈表中查找呢?首先你要在定義用于比較字符串一個(gè)函數(shù): int compare_chars(void const *a, void const *b) { if(*(char*)a == *(char *)b) return 0; else return 1; } 當(dāng)然你不必這樣來(lái)寫,因?yàn)镃語(yǔ)言函數(shù)庫(kù)里面有這樣的函數(shù) strcmp( const char *string1, const char *string2 ); 所以你就可以直接使用下面的代碼來(lái)實(shí)現(xiàn)在字符串鏈表中查找字符值的功能 Desired_node = Search_list(root, &desired_value, strcmp); 這樣,可以不必修改Search_list函數(shù),而使得Search_list函數(shù)的功能更加通用。 C語(yǔ)言之面向?qū)ο?/strong> 我們經(jīng)常說C語(yǔ)言是面向過程的語(yǔ)言,而C++、JAVA是面向?qū)ο蟮模敲嫦驅(qū)ο蟛⒉皇荂++、JAVA的專利,C語(yǔ)言里面也有面向?qū)ο蟮乃枷耄热缥覀兘?jīng)常使用的結(jié)構(gòu)體。 struct student { char name[256]; int age; }; 學(xué)生的姓名和年齡,就是學(xué)生自身的屬性,和C++里面的成員變量是一樣的概念,但是這個(gè)結(jié)構(gòu)體里面并沒有體現(xiàn)出方法的使用。在面向?qū)ο笾杏蟹庋b的概念,結(jié)構(gòu)體中的成員我們不應(yīng)該直接訪問,而應(yīng)該通過方法訪問,我們可以添加訪問結(jié)構(gòu)體成員變量的方法。 char* get_name(student * self);//獲取學(xué)生姓名 void set_name(student * self, char* name);//設(shè)置學(xué)生姓名 char* get_name(student * self) { return self->name; } void set_name(student * self, char* name) { strncpy(self->name, name, sizeof(self->name)); } 此處省略age的設(shè)置和獲取功能。 現(xiàn)在類的數(shù)據(jù)、方法都有了,下一步就是要使用類創(chuàng)建、初始化、析構(gòu)、銷毀對(duì)象,在C++中有new、delete操作符負(fù)責(zé)創(chuàng)建和銷毀,使用C語(yǔ)言實(shí)現(xiàn)如下: student * student _create(void);// 對(duì)象創(chuàng)建和初始化 void student _destroy(student * self);// 對(duì)象析構(gòu)和銷毀 student * student _create(void) { student * self = malloc(sizeof(student)); memset(self->name, 0x00, sizeof(self->name)); self->age = 0; return self; } void student _destroy(student * self) { free(self); } 至此,我們就可以采用面向?qū)ο蟮姆绞絹?lái)編寫代碼了。 student * student1= NULL; student1 = student _create();//創(chuàng)建對(duì)象 set_name(student1, "mary");//初始化student1的名字為mary set_age(student1, 20); //初始化student1的年齡為20 get_name(student1);//獲取student1的姓名 student _destroy(student1);//銷毀對(duì)象 當(dāng)然C語(yǔ)言還有很多強(qiáng)大的功能,比如可變參數(shù)的函數(shù)設(shè)計(jì),無(wú)一例外都要借助于指針來(lái)實(shí)現(xiàn)。以上內(nèi)容參考于網(wǎng)絡(luò)資源,如有錯(cuò)誤之處,懇請(qǐng)指正。 |