void 指針的背后藏著什么? void是什么意思

void是什么意思(void 指針的背后藏著什么?)
1 不能動的“地址”之 void指針

void 指針的背后藏著什么? void是什么意思

文章插圖

1.1 void指針初探void *表示一個“不知道類型”的指針 , 也就不知道從這個指針地址開始多少字節為一個數據 。 和用int表示指針異曲同工 , 只是更明確是“指針” 。
因此void *只能表示一個地址 , 不能用來&取值 , 也不能++和--移動指針 , 因此不知道多少字節是一個數據單位 。
    int nums[] = {3,5,6,7,9};    void* ptr1 = nums;    //int i = *ptr1; // 對于void指針沒法直接取值    int* ptr2 = (int*)nums;    printf("%d,%d/n",ptr1,ptr2);    int i = *ptr2;    printf("%d/n",i);從輸出結果可以看出 , 無論是無類型的void指針還是int類型指針 , 指向的地址都是一樣的:
void 指針的背后藏著什么? void是什么意思

文章插圖

PS:void *就是一個不能動的“地址” , 在進行&、移動指針之前必須轉型為類型指針 。
1.2 void指針的用途
void 指針的背后藏著什么? void是什么意思

文章插圖

這里我們看一下我們之前了解的memset函數 , 其第一個參數就是一個void指針 , 它可以幫我們屏蔽各種不同類型指針的差異 。
如下面代碼所示 , 我們既可以傳入一個int類型數組的指針 , 也可以傳入一個char類型數組的指針:
    int nums[20];    memset(nums,0,sizeof(nums));    char chs[2];    memset(chs,0,sizeof(chs));那么 , 我們也可以試著自己動手模擬一下這個memset函數 , 暫且命名為mymemset吧:
void mymemset(void *data,int num,int byteSize){    // char就是一個字節 , 而計算機中是以字節為單位存儲的    char *ptr = (char*)data;    int i;    for(i=0;i<byteSize;i++)    {        *ptr=num;        ptr++;    }}int main(int argc, char *argv[]){    int nums[20];    mymemset(nums,0,sizeof(nums));    int i,len=sizeof(nums)/sizeof(int);    for(i=0;i<len;i++)    {        printf("%d ",nums[i]);    }    printf("/n");    return 0;}在這個mymemset函數中 , 我們利用void指針接收不同類型的指針 , 利用char類型(一個字節)逐個字節讀取內存中的每一個字節 , 最后依次填充指定的數字 。
由于char類型是一個具體類型 , 所以可以使用++或者--進行指針的移動 。
對于結構體類型 , 也可以使用我們的mymemset函數:
typedef struct _Person{    char *name;    int age;} Person;Person p1;mymemset(&p1,0,sizeof(Person));printf("p1.Age:%d/n",p1.age);最終的運行結果如下圖所示:
void 指針的背后藏著什么? void是什么意思

文章插圖

void *的用途:在只知道內存 , 但是不知道是什么類型的時候 。
2 函數指針2.1 指向函數的指針我們可以在C中輕松地定義一個函數指針:
typedef void (*intFunc)(int i);這里我們定義了一個無返回值的 , 只有一個int類型參數的函數指針intFunc 。
我們可以在main函數中使用這個函數指針來指向一個具體的函數(這個具體的函數定義需要和函數指針的定義一致):
void test1(int age){    printf("test1:%d/n",age);}int main(void){        // 聲明一個intFunc類型的函數指針    intFunc f1 = test1;    // 執行f1函數指針所指向的代碼區    f1(8);    return 0;}

推薦閱讀