廊坊新闻网-主流媒体,廊坊城市门户

焦点要闻:void是什么意思(void 指针的背后藏着什么?)

2022-09-05 21:40:06 来源:刀哥百科

void是什么意思(void指针背后隐藏着什么?)

1个不可移动“地址”的空指针

1.1空指针

Void *表示一个“未知类型”的指针,即从这个指针地址开始的一段数据有多少字节是未知的。和用int表示一个指针是一样的,但是更具体的是“指针”。

所以void *只能代表一个地址,不能用来& value,也不能++和-移动指针,所以不知道多少字节是一个数据单元。


(相关资料图)

int nums[] = {3,5,6,7,9};    void* ptr1 = nums;    //int i = *ptr1; // 对于void指针没法直接取值    int*&红豆博客nbsp;ptr2 = (int*)nums;    printf("%d,%d\n",ptr1,ptr2);    int i = *ptr2;    printf("%d\n",i);

从输出结果可以看出,无论是非类型化void指针还是int指针,指向的地址都是一样的:

Ps: void *是一个不可移动的“地址”,它必须在移动指针之前被转换成一个类型指针。

1.2 void指针的用途

这里,我们来看看之前学过的memset函数。第一个参数是一个void指针,可以帮助我们屏蔽不同类型指针的差异。

如下面的代码所示,我们可以传入一个指向int类型数组的指针或一个指向char类型数组的指针:

int nums对于结构类型,我们也可以使用mymemset函数:;    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

在这个mymemset函数中,我们用void指针接收不同类型的指针,用char类型(一个字节)逐个读取内存中的每个字节,最后依次填充指定的数字。

因为char类型是具体类型,所以可以使用++或-来移动指针。

[20]

typedef struct _Person{    char *name;    int age;} Person;Person p1;mymemset(&p1,0,sizeof(Person));printf("p1.Age:%d\n",p1.age);

红豆博客最终运行结果如下图所示:

void *的用途:只知道内存,但不知道是什么类型的时候。

2函数指针2.1指向函数的指针

我们可以很容易地在C中定义一个函数指针:

typedef void (*intFunc)(int i);

这里我们定义了一个函数指针intFunc,没有返回值,只有一个int类型的参数。

我们可以在主函数中使用这个函数指针指向一个特定的函数(这个特定的函数定义需要和函数指针的定义一致):

void test1(int age){    printf("test1:%d\n",age);}int main(void){        // 声明一个intFunc类型的函数指针    intFunc f1 = test1;    // 执行f1函数指针所指向的代码区    f1(8);    return 0;}

最终运行结果如下图所示,执行函数指针f1执行其指向的特定函数:

2.2函数指针的基本用法

这里我们通过一个小案例对函数指针的使用做一个基本的介绍。相信大部分C#或Java程序员对foreach都很熟悉,所以我们模拟foreach对int数组中的值进行不同的处理。for循环中体现的代码是重用的,但是如何处理数据是不确定的,所以处理数据的逻辑由函数指针指定。

void foreachNums(int *nums,int len,intFunc func){    int i;    for(i=0;idata2,则返回正数void *getMax(void *data,int unitSize,int length,compareFunc func){    int i;    char *ptr = (char*)data;    char *max = ptr;        for(i=1;i0)        {            max = item;        }    }    return max;}

这里可以看到,在getMax中比较几个字节是由compareFunc指向的函数完成的,getMax根本不在乎。

(2)定义符合函数指针定义的不同类型的函数:

int intDataCompare(void *data1,void *data2){    int *ptr1 = (int*)data1;    int *ptr2 = (int*)data2;    int i1=*ptr1;    int i2=*ptr2;    return i1-i2;}typedef struct _Dog{    char *name;    int age;} Dog;int dogDataCompare(void *data1,void *data2){    Dog *dog1 = (Dog*)data1;    Dog *dog2 = (Dog*)data2;    return (dog1->age)-(dog2->age);}

(3)在主函数中调用int类型和structure类型:

int main(int argc, char *argv[]){    // test1:int类型求最大值    int nums[] = { 3,5,8,7,6 };    int *pMax = (int *)getMax(nums,sizeof(int),sizeof(nums)/sizeof(int),        intDataCompare);    int max = *pMax;    printf("%d\n",max);    // test2:结构体类型求最大值    Dog dogs[] ={{"沙皮",3},{"腊肠",10},{"哈士奇",5},        {"京巴",8},{"大狗",2}};    Dog *pDog = (Dog *)getMax(dogs,sizeof(Dog),        sizeof(dogs)/sizeof(Dog),dogDataCompare);    printf("%s=%d",pDog->name,pDog->age);    return 0;}

最终运行结果如下图所示:

3.2 C-自定义排序中包含的qsort功能

Qsort包含在头文件中。这个函数根据你给的比较条件快速排序,通过移动指针来排序。排序后的结果仍然放在原始数组中。

要使用qsort函数,必须自己写一个比较函数。我们可以看看qsort函数的原型:

void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );    int nums[] = { 3,5,8,7,6 };    qsort(nums,sizeof(nums)/sizeof(int),sizeof(int),intDataCompare);    int i;    for(i=0;i

那么,快速排序后有结果吗?答案是肯定的,我们可以引入各种比较方法,可以升序排序,也可以降序排序。

——结尾——

关键词: 如下图所示 类型数组