0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文揭秘C語言的void指針

工程師進階筆記 ? 來源:小麥大叔 ? 2023-02-02 17:18 ? 次閱讀

1 不能動的“地址”之 void指針

1.1 void指針初探

void *表示一個“不知道類型”的指針,也就不知道從這個指針地址開始多少字節(jié)為一個數(shù)據(jù)。和用int表示指針異曲同工,只是更明確是“指針”。

因此void *只能表示一個地址,不能用來&取值,也不能++和--移動指針,因此不知道多少字節(jié)是一個數(shù)據(jù)單位。

intnums[]={3,5,6,7,9};
void*ptr1=nums;
//inti=*ptr1;//對于void指針沒法直接取值
int*ptr2=(int*)nums;
printf("%d,%d
",ptr1,ptr2);
inti=*ptr2;
printf("%d
",i);

從輸出結(jié)果可以看出,無論是無類型的void指針還是int類型指針,指向的地址都是一樣的:

89ca1ff4-a2d8-11ed-bfe3-dac502259ad0.png

PS:void *就是一個不能動的“地址”,在進行&、移動指針之前必須轉(zhuǎn)型為類型指針。

1.2 void指針的用途

89d7eaf8-a2d8-11ed-bfe3-dac502259ad0.png

這里我們看一下我們之前了解的memset函數(shù),其第一個參數(shù)就是一個void指針,它可以幫我們屏蔽各種不同類型指針的差異。 如下面代碼所示,我們既可以傳入一個int類型數(shù)組的指針,也可以傳入一個char類型數(shù)組的指針:

intnums[20];
memset(nums,0,sizeof(nums));
charchs[2];
memset(chs,0,sizeof(chs));

那么,我們也可以試著自己動手模擬一下這個memset函數(shù),暫且命名為mymemset吧:

voidmymemset(void*data,intnum,intbyteSize)
{
//char就是一個字節(jié),而計算機中是以字節(jié)為單位存儲的
char*ptr=(char*)data;
inti;
for(i=0;i

在這個mymemset函數(shù)中,我們利用void指針接收不同類型的指針,利用char類型(一個字節(jié))逐個字節(jié)讀取內(nèi)存中的每一個字節(jié),最后依次填充指定的數(shù)字。

由于char類型是一個具體類型,所以可以使用++或者--進行指針的移動。

對于結(jié)構(gòu)體類型,也可以使用我們的mymemset函數(shù):

typedefstruct_Person
{
char*name;
intage;
}Person;

Personp1;
mymemset(&p1,0,sizeof(Person));
printf("p1.Age:%d
",p1.age);

最終的運行結(jié)果如下圖所示:

89ec4638-a2d8-11ed-bfe3-dac502259ad0.png

void *的用途:在只知道內(nèi)存,但是不知道是什么類型的時候。

2 函數(shù)指針

2.1 指向函數(shù)的指針

我們可以在C中輕松地定義一個函數(shù)指針:

typedefvoid(*intFunc)(inti);

這里我們定義了一個無返回值的,只有一個int類型參數(shù)的函數(shù)指針intFunc。

我們可以在main函數(shù)中使用這個函數(shù)指針來指向一個具體的函數(shù)(這個具體的函數(shù)定義需要和函數(shù)指針的定義一致):

voidtest1(intage){

printf("test1:%d
",age);
}

intmain(void){

//聲明一個intFunc類型的函數(shù)指針
intFuncf1=test1;
//執(zhí)行f1函數(shù)指針?biāo)赶虻拇a區(qū)
f1(8);
return0;
}
最終運行結(jié)果如下圖所示,執(zhí)行函數(shù)指針f1即執(zhí)行了其所指向的具體的函數(shù):

89fece66-a2d8-11ed-bfe3-dac502259ad0.png

2.2 函數(shù)指針的基本使用

這里我們通過一個小案例來對函數(shù)指針做一個基本的使用介紹。相信大部分的C#Java程序員都很熟悉foreach,那么我們就來模擬foreach對int數(shù)組中的值進行不同的處理。具體體現(xiàn)為for循環(huán)的代碼是復(fù)用的,但是怎么處理這些數(shù)據(jù)不確定,因此把處理數(shù)據(jù)的邏輯由函數(shù)指針指定。

voidforeachNums(int*nums,intlen,intFuncfunc)
{
inti;
for(i=0;i
在foreachNums函數(shù)中,我們定義了一個intFunc函數(shù)指針,printNum函數(shù)是滿足intFunc定義的一個具體的函數(shù)。

下面我們在main函數(shù)中將printNum函數(shù)作為函數(shù)指針傳遞給foreachNums函數(shù)。

intnums[]={1,5,666,23423,223};
foreachNums(nums,sizeof(nums)/sizeof(int),printNum);
最終運行的結(jié)果如下圖所示:

8a108c14-a2d8-11ed-bfe3-dac502259ad0.png

通過函數(shù)指針,我們可以屏蔽各種具體處理方法的不同,也就是將不確定的因素都依賴于抽象,這也是面向抽象或面向接口編程的精髓。

三、函數(shù)指針應(yīng)用案例

3.1 計算任意類型的最大值

(1)定義函數(shù)指針及getMax主體:

typedefint(*compareFunc)(void*data1,void*data2);
// getMax 函數(shù)參數(shù)說明:
//data待比較數(shù)據(jù)數(shù)組的首地址,uniteSize單元字節(jié)個數(shù)
// length:數(shù)據(jù)的長度。{1,3,5,6}:length=4
//比較data1和data2指向的數(shù)據(jù)做比較,
//如果data1>data2,則返回正數(shù)
void*getMax(void*data,intunitSize,intlength,compareFuncfunc)
{
inti;
char*ptr=(char*)data;
char*max=ptr;

for(i=1;i0)
{
max=item;
}
}

returnmax;
}
這里可以看到,在getMax中到底取幾個字節(jié)去比較都是由compareFunc所指向的函數(shù)去做,getMax根本不用關(guān)心。

(2)定義符合函數(shù)指針定義的不同類型的函數(shù):

intintDataCompare(void*data1,void*data2)
{
int*ptr1=(int*)data1;
int*ptr2=(int*)data2;

inti1=*ptr1;
inti2=*ptr2;

returni1-i2;
}

typedefstruct_Dog
{
char*name;
intage;
}Dog;

intdogDataCompare(void*data1,void*data2)
{
Dog*dog1=(Dog*)data1;
Dog*dog2=(Dog*)data2;

return(dog1->age)-(dog2->age);
}

(3)在main函數(shù)中針對int類型和結(jié)構(gòu)體類型進行調(diào)用:

intmain(intargc,char*argv[])
{
//test1:int類型求最大值
intnums[]={3,5,8,7,6};
int*pMax=(int*)getMax(nums,sizeof(int),sizeof(nums)/sizeof(int),
intDataCompare);
intmax=*pMax;
printf("%d
",max);
//test2:結(jié)構(gòu)體類型求最大值
Dogdogs[]={{"沙皮",3},{"臘腸",10},{"哈士奇",5},
{"京巴",8},{"大狗",2}};
Dog*pDog=(Dog*)getMax(dogs,sizeof(Dog),
sizeof(dogs)/sizeof(Dog),dogDataCompare);
printf("%s=%d",pDog->name,pDog->age);

return0;
}

最終運行結(jié)果如下圖所示:

8a221a42-a2d8-11ed-bfe3-dac502259ad0.png

3.2 C 中自帶的qsort函數(shù)—自定義排序

qsort包含在頭文件中,此函數(shù)根據(jù)你給的比較條件進行快速排序,通過指針移動實現(xiàn)排序。排序之后的結(jié)果仍然放在原數(shù)組中。

使用qsort函數(shù)必須自己寫一個比較函數(shù)。我們可以看看qsort函數(shù)的原型:

voidqsort(void*base,size_tnum,size_tsize,int(*comparator)(constvoid*,constvoid*));
intnums[]={3,5,8,7,6};
qsort(nums,sizeof(nums)/sizeof(int),sizeof(int),intDataCompare);
inti;
for(i=0;i
那么,快速排序后是否有結(jié)果呢?答案是肯定的,我們可以傳入各種比較方法,可以升序排序也可以降序排序。

8a3678d4-a2d8-11ed-bfe3-dac502259ad0.png

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134143
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4237

    瀏覽量

    61971
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    475

    瀏覽量

    70459
  • void
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    9839
  • 函數(shù)指針
    +關(guān)注

    關(guān)注

    2

    文章

    55

    瀏覽量

    3760

原文標(biāo)題:揭秘 C 語言的 void 指針

文章出處:【微信號:工程師進階筆記,微信公眾號:工程師進階筆記】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    void指針簡述

    指針指向的數(shù)據(jù)類型有多種再或者程序員僅僅是想通過指針來操作段內(nèi)存空間。這個時候可以將指針申明為vo
    的頭像 發(fā)表于 09-09 08:57 ?1615次閱讀
    <b class='flag-5'>void</b><b class='flag-5'>指針</b>簡述

    C語言void指針的基本認識及典型應(yīng)用

    C語言中,*類型就是指針類型,比如 int *p,double *q,雖然是不樣的指針,但是大小卻
    發(fā)表于 02-01 09:26 ?975次閱讀

    c語言指針詳解

    。9、空指針 指向空,或者說不指向任何東西。在C語言中,我們讓指針變量賦值為NULL表示個空指針
    發(fā)表于 03-26 09:51

    什么是void指針?void指針有何功能

    [導(dǎo)讀] 要比較靈活的使用C語言實現(xiàn)些高層級的框架時,需要掌握些進階編程技巧,這篇來談?wù)?b class='flag-5'>void指針
    發(fā)表于 02-21 06:01

    C語言voidvoid指針深層探索

    1.概述 本文將對void關(guān)鍵字的深刻含義進行解說,并詳述voidvoid指針類型的使用方法與技巧。 2.void的含義
    發(fā)表于 09-21 11:36 ?166次下載

    C語言指針電子教程

    本資料是份不錯的關(guān)于C語言指針的電子教程,希望對大家有所幫助... 指針簡介 指針
    發(fā)表于 07-30 16:00 ?77次下載

    講通C語言指針資料下載

    電子發(fā)燒友網(wǎng)為你提供講通C語言指針資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計、用戶指南
    發(fā)表于 04-24 08:44 ?10次下載
    <b class='flag-5'>一</b><b class='flag-5'>文</b>講通<b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>指針</b>資料下載

    淺談void指針的高階用法

    要比較靈活的使用C語言實現(xiàn)些高層級的框架時,需要掌握些進階編程技巧,這篇來談?wù)?b class='flag-5'>void指針
    的頭像 發(fā)表于 08-09 15:54 ?1525次閱讀
    淺談<b class='flag-5'>void</b> 型<b class='flag-5'>指針</b>的高階用法

    STM32編程:void指針高階用法舉例,設(shè)計個通用掉電存儲子系統(tǒng)

    [導(dǎo)讀] 要比較靈活的使用C語言實現(xiàn)些高層級的框架時,需要掌握些進階編程技巧,這篇來談?wù)?b class='flag-5'>void指針
    發(fā)表于 12-27 18:47 ?10次下載
    STM32編程:<b class='flag-5'>void</b><b class='flag-5'>指針</b>高階用法舉例,設(shè)計<b class='flag-5'>一</b>個通用掉電存儲子系統(tǒng)

    STM32編程:void指針高階用法

    [導(dǎo)讀] 要比較靈活的使用C語言實現(xiàn)些高層級的框架時,需要掌握些進階編程技巧,這篇來談?wù)?b class='flag-5'>void指針
    發(fā)表于 02-07 11:14 ?2次下載
    STM32編程:<b class='flag-5'>void</b><b class='flag-5'>指針</b>高階用法

    C語言-指針定義與使用

    指針在很多書本上都是當(dāng)做重點來介紹,作為C語言的靈魂,項目里指針無處不在。 這篇文章介紹指針的基本用法。
    的頭像 發(fā)表于 08-14 10:02 ?1251次閱讀

    C語言-void類型作為萬能指針類型

    空類型`。 void abc; //這是錯誤的 但是`void`是可以定義指針的,`void*`表示萬能型指針類型,可以與任何
    的頭像 發(fā)表于 08-14 10:04 ?1642次閱讀

    C語言進階】C語言指針的高階用法

    C語言進階】C語言指針的高階用法
    的頭像 發(fā)表于 08-31 13:24 ?2156次閱讀

    什么是void指針

    C語言中,*類型就是指針類型,比如 int *p,double *q,雖然是不樣的指針,但是大小卻
    的頭像 發(fā)表于 02-13 15:02 ?1279次閱讀

    什么是C語言void*)類型

    大家在C語言的學(xué)習(xí)過程中肯定見過各種指針符號,如 int*, char* 等等等等。顧名思義,int*就是個指向整形的指針,而char*
    的頭像 發(fā)表于 02-24 14:31 ?2729次閱讀