衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

一文揭秘C語言的void指針

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

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

1.1 void指針初探

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

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

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);

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

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

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

1.2 void指針的用途

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

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

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

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

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

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

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

對于結構體類型,也可以使用我們的mymemset函數:

typedefstruct_Person
{
char*name;
intage;
}Person;

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

最終的運行結果如下圖所示:

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

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

2 函數指針

2.1 指向函數的指針

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

typedefvoid(*intFunc)(inti);

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

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

voidtest1(intage){

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

intmain(void){

//聲明一個intFunc類型的函數指針
intFuncf1=test1;
//執行f1函數指針所指向的代碼區
f1(8);
return0;
}
最終運行結果如下圖所示,執行函數指針f1即執行了其所指向的具體的函數:

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

2.2 函數指針的基本使用

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

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

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

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

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

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

三、函數指針應用案例

3.1 計算任意類型的最大值

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

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

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

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

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

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函數中針對int類型和結構體類型進行調用:

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:結構體類型求最大值
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;
}

最終運行結果如下圖所示:

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

3.2 C 中自帶的qsort函數—自定義排序

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

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

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
那么,快速排序后是否有結果呢?答案是肯定的,我們可以傳入各種比較方法,可以升序排序也可以降序排序。

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

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7614

    瀏覽量

    137712
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62969
  • 指針
    +關注

    關注

    1

    文章

    481

    瀏覽量

    70608
  • void
    +關注

    關注

    0

    文章

    23

    瀏覽量

    9900
  • 函數指針
    +關注

    關注

    2

    文章

    56

    瀏覽量

    3835

原文標題:揭秘 C 語言的 void 指針

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

收藏 人收藏

    評論

    相關推薦

    C語言void指針的基本認識及典型應用

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

    c語言指針詳解

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

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

    [導讀] 要比較靈活的使用C語言實現些高層級的框架時,需要掌握些進階編程技巧,這篇來談談void指針
    發表于 02-21 06:01

    C語言voidvoid指針深層探索

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

    C語言指針電子教程

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

    C語言的精髓——指針詳解

    C語言的精髓——指針詳解
    發表于 11-30 14:43 ?17次下載

    講通C語言指針資料下載

    電子發燒友網為你提供講通C語言指針資料下載的電子資料下載,更有其他相關的電路圖、源代碼、課件教程、中文資料、英文資料、參考設計、用戶指南
    發表于 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語言實現些高層級的框架時,需要掌握些進階編程技巧,這篇來談談void指針
    的頭像 發表于 08-09 15:54 ?1691次閱讀
    淺談<b class='flag-5'>void</b> 型<b class='flag-5'>指針</b>的高階用法

    STM32編程:void指針高階用法舉例,設計個通用掉電存儲子系統

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

    STM32編程:void指針高階用法

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

    C語言-指針定義與使用

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

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

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

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

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

    什么是void指針

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

    什么是C語言void*)類型

    大家在C語言的學習過程中肯定見過各種指針符號,如 int*, char* 等等等等。顧名思義,int*就是個指向整形的指針,而char*
    的頭像 發表于 02-24 14:31 ?3417次閱讀
    太阳城百家乐官网娱乐官方网| YY百家乐的玩法技巧和规则| 百家乐官网b28博你发v| 百家乐官网真人游戏棋牌| 玩百家乐官网出千方法| 百家乐官网网上真钱麻将| 澳门百家乐官网博彩网| 宝马会百家乐官网现金网| 百家乐官网庄闲作千| 家百家乐官网破解软件| 富易堂百家乐官网娱乐城| 百家乐官网平台注册送现金| 百家乐官网最新庄闲投注法| 赌场百家乐官网赢钱| 赌场百家乐官网玩法介绍| 历史百家乐官网路单图| 百家乐官网平台有什么优惠| 最新百家乐官网的玩法技巧和规则| 百家乐视频下载| 百家乐隔一数打投注法| 百家乐赌场赌场平台| 威尼斯人娱乐场 五星| bet365注册 jxhymp| 云龙县| 澳门百家乐官网打缆| 龙南县| 百家乐官网赌博凯时娱乐| 百家乐官网平玩法可以吗| 百家乐庄闲必赢| 莫斯科百家乐的玩法技巧和规则 | 凯旋门娱乐城开户| 百家乐官网电脑上怎么赌| KK百家乐官网的玩法技巧和规则| 百家乐投注技巧公式| 威尼斯人娱乐城图片| 宝胜娱乐| 百家乐官网那个平台信誉高| 百家乐官网倍投软件| 海港城百家乐的玩法技巧和规则| 太阳城娱乐城申博| 免佣百家乐官网规则|