同事用void把我給秀翻了!
1、聊一聊
今天跟大家推薦的這首歌最近應(yīng)該挺火的,不過沒辦法插入AGA的原版歌曲,大家覺得不錯(cuò)可以去找找原版歌曲收錄一下。
昨天建立了"最后一個(gè)bug"技術(shù)交流群,由于群成員超過200就無(wú)法直接通過群二維碼加入,如果大家想加入掃描下面作者的個(gè)人微信號(hào)然后拉你入群。
2、簡(jiǎn)單認(rèn)識(shí)一下void
今天跟大家介紹的知識(shí)是C語(yǔ)言中的void關(guān)鍵字的用法,void在大部分小伙伴的程序中都只是用于函數(shù)無(wú)參數(shù)傳入,或者無(wú)類型返回。
然而我們平時(shí)所定義的變量都會(huì)有具體的類型,int,float,char等等,那是否有void類型的變量呢?大家可以動(dòng)手實(shí)驗(yàn)一下,答案是:不行,編譯會(huì)出錯(cuò)。

上圖很明顯編譯器不允許定義void類型的變量,變量都是需要占用一定內(nèi)存的,既然void表示無(wú)類型,編譯器自然也就不知道該為其分配多大的內(nèi)存,于是造成編譯失敗。
雖然void不能直接修飾變量,但是其可以用于修飾指針的指向即無(wú)類型指針void*,無(wú)類型指針那就有意義了,無(wú)類型指針不是一定要指向無(wú)類型數(shù)據(jù),而是可以指向任意類型的數(shù)據(jù)。
3、void * 基本操作?
大家其實(shí)在使用動(dòng)態(tài)內(nèi)存分配的使用就已經(jīng)遇到了void *的使用,來(lái)我們一起看看如下幾個(gè)標(biāo)準(zhǔn)函數(shù)的原型定義:

? ??
上面這些函數(shù)都是與內(nèi)存操作有關(guān)的函數(shù),可能一些小伙伴使用過也不一定知道每個(gè)參數(shù)的具體類型是什么,這些void*部分的形參所傳入的實(shí)參都是不需要進(jìn)行強(qiáng)制類型轉(zhuǎn)化的,所以根本就不需要關(guān)注傳入指針?biāo)赶虻木唧w類型,然而函數(shù)所返回的void *一般都需要通過強(qiáng)制類型轉(zhuǎn)化為對(duì)應(yīng)的具體類型,除非你最后所傳遞的變量也是void*類型。
參考void*用法:
1#include?
2#include?
3#include??
4
5#define?NUM?10
6/*************************************
7?*?Fuction:了解一下void*的使用?
8?*?Author?:?(公眾號(hào):最后一個(gè)bug)?
9?*************************************/
10int?main(int?argc,?char?*argv[])?{
11????int?*p1?=?(int?*)malloc(NUM*sizeof(int));?
12????int?*p2?=?(int?*)malloc(NUM*sizeof(int));?
13????int??i?=?0;
14
15????//初始化p1?
16????for(i?=?0;i?17????{
18????????*(p1+i)?=?i;
19????}
20????//進(jìn)行內(nèi)存copy?
21????memcpy(p2,p1,NUM*sizeof(int));
22
23????//輸出另外一個(gè)分配的內(nèi)存?
24????for(i?=?0;i?25????{
26???????printf("%d,",*(p2+i));?
27????}???
28????//釋放內(nèi)存?
29????free(p1);
30????free(p2);
31????return?0;
32} 運(yùn)行結(jié)果:

4、使用void * 實(shí)現(xiàn)無(wú)類型數(shù)據(jù)封裝
為了保持文章的完整性,也許這里才是作者最想跟大家介紹的,void*既然如此的靈活一定大有用處,如果僅僅只是用來(lái)簡(jiǎn)單的傳遞參數(shù)似乎有點(diǎn)大材小用,我們得把其用到上層的軟件設(shè)計(jì)上來(lái)。
在一些項(xiàng)目中經(jīng)??吹接行』锇榘褦?shù)據(jù)類型轉(zhuǎn)來(lái)轉(zhuǎn)去,甚至有時(shí)候?yàn)榱艘粋€(gè)數(shù)據(jù)類型的變化還得重新寫一個(gè)僅僅數(shù)據(jù)類型不同的函數(shù),這樣的代碼上萬(wàn)行代碼指日可待,按下面我們以一個(gè)例子來(lái)跟大家介紹一種辦法能夠減少數(shù)據(jù)類型變化所帶來(lái)的程序重復(fù)代碼的增加。
參考實(shí)例:
1#include?
2#include?
3/**********************************?
4?*?Fuction?:?add
5?*?descir?:??加法的相關(guān)數(shù)據(jù)及處理辦法?
6?*?Author?:?(公眾號(hào):最后一個(gè)bug)
7?**********************************/?
8typedef?struct?_tag_Add
9{
10????int?a;
11????int?b;
12????int?result;
13}sAdd;
14
15void?Add(void?*param)
16{
17????sAdd?*p?=?(sAdd?*)?param;
18????p->result?=?p->a?+?p->b;
19}
20/**********************************?
21?*?Fuction?:?add
22?*?descir?:??乘法的相關(guān)數(shù)據(jù)及處理辦法?
23?*?Author?:?(公眾號(hào):最后一個(gè)bug)
24?**********************************/?
25typedef?struct?_tag_Mul
26{
27????float?a;
28????float?b;
29????float?result;
30}sMul;
31
32void?Mul(void?*param)
33{
34????sMul?*p?=?(sMul?*)?param;
35????p->result?=?p->a?*?p->b;
36}
37
38/*************************************?
39?*?Fuction?:?sCal
40?*?descir?:??公共的調(diào)用接口?
41?*?Author?:?(公眾號(hào):最后一個(gè)bug)
42?************************************/?
43void?sCal(void?*param,void?*fuc)
44{
45????((void?(*)(void*))fuc)(param);
46}
47
48/**********************************?
49?*?Fuction?:?main
50?*?descir?:?應(yīng)用接口實(shí)例?
51?*?Author?:?(公眾號(hào):最后一個(gè)bug)
52?**********************************/??
53int?main(void)
54{
55????sAdd?stAdd;
56????sMul?stMul;
57
58????//數(shù)據(jù)初始化?
59????stAdd.a?=?10;
60????stAdd.b?=?20;
61
62????stMul.a?=?5;
63????stMul.b?=?5;
64????//接口直接用?
65????sCal(&stAdd,Add);
66????sCal(&stMul,Mul);
67????//對(duì)應(yīng)的輸出?
68????printf("a?+?b?=?%d\n",stAdd.result);
69????printf("a?*?b?=?%f\n",stMul.result);
70????printf("公眾號(hào):最后一個(gè)bug\n");
71????return?0;
72?}?
運(yùn)行結(jié)果:

分析一下:
上面的例子可能還是無(wú)法完全彰顯void*的強(qiáng)悍之處了,不過其主要的作用就是為了隱藏?cái)?shù)據(jù)類型,大家也可以理解為一種數(shù)據(jù)類型的抽象處理,這也是面向?qū)ο缶幊痰囊环N體現(xiàn)。
4、最后小結(jié)
對(duì)于void這個(gè)關(guān)鍵字的使用bug菌就先講這么多吧!大家一定要記得對(duì)于一些編程技巧一定要嘗試著去使用,可能達(dá)到項(xiàng)目目標(biāo)的方式有很多種,但是一些好的設(shè)計(jì)不僅僅會(huì)讓你的代碼增色不少,同時(shí)也會(huì)讓同事們覺得你是一個(gè)喜歡專研技術(shù)的人。

