C++ void*解惑

C++ void*解惑,第1张

概述最近遇到void *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它。 在哪遇到了?   线程创建函数pthread_create()的最后一个参数void *arg,嗯?传地址还是传值?传值好像有警告。 还有别的出现的地方呢     看memcpy(),返回值和参数都有void *,那又怎么传呢?下面我们首先来说说void *是什么。 一:void *是什么? C

最近遇到voID *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它。

在哪遇到了?

 


线程创建函数pthread_create()的最后一个参数voID *arg,嗯?传地址还是传值?传值好像有警告。

还有别的出现的地方呢

 

 

看memcpy(),返回值和参数都有voID *,那又怎么传呢?下面我们首先来说说voID *是什么。

一:voID *是什么?

C语言中,*类型就是指针类型。比如 int *p,double *q,虽然是不一样的指针,但是大小却一样sizeof(p) == sizeof(q),其实很容易理解,因为他们都是同一种类型*类型的。C语言是强类型的语言。对类型的区分十分严格。那这两个有什么不同点吗?有,+1就不同了,看下面的图:

 


也就是对于一个指针而言,如果我们在前面规定了它的类型。那就相当于决定了它的“跳跃力”。“跳跃力”就比如说上面图中int跳了4个字节,但是double跳了8个字节。基于这样的理解,我要对voID *下定义了:

voID * 是一个跳跃力未定的指针
二:跳跃力什么时候定?

这就是它的神奇之处了,我们可以自己控制在需要的时候将它实现为需要的类型。这样的好处是:编程时候节约代码,实现泛型编程。比如我们经常写的排序算法,就可以这么写:


#include <stdio.h>
#include <string.h>
static voID Swap(char *vp1,char *vp2,int wIDth)
{
char tmp;
if ( vp1 != vp2 ) {
while ( wIDth-- ) {
tmp = *vp1;
*vp1++ = *vp2;
*vp2++ = tmp;
}
}
}
voID BubbleSort(voID *base,int n,int elem_size,
int (*compare)( voID *,voID * ))
{
int i,last,end = n - 1;
char *elem_addr1,*elem_addr2;
while (end > 0) {
last = 0;
for (i = 0; i < end; i++) {
elem_addr1 = (char *)base + i * elem_size;
elem_addr2 = (char *)base + (i + 1) * elem_size;
if (compare( elem_addr1,elem_addr2 ) > 0) {
Swap(elem_addr1,elem_addr2,elem_size);
last = i;
}
}
end = last;
}
}
int compare_int(voID *elem1,voID *elem2)
{
return (*(int *)elem1 - *(int *)elem2);
}
int compare_double(voID *elem1,voID *elem2)
{
return (*(double *)elem1 > *(double *)elem2) ? 1 : 0;
}
int main(int argc,char *argv[])
{
int num_int[8] = {8,7,6,5,4,3,2,1};
double num_double[8] = {8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1};
int i;
BubbleSort(num_int,8,sizeof(int),compare_int);
for (i = 0; i < 8; i++) {
printf("%d ",num_int[i]);
}
printf("\n");
BubbleSort(num_double,sizeof(double),compare_double);
for (i = 0; i < 8; i++) {
printf("%.1f ",num_double[i]);
}
printf("\n");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

 


上面的compare_int和compare_double就是定它跳跃力的时候。

三:再来说memcpy

我们先来看下面这段代 码:

#include<stdio.h>
#include<string.h>

struct stu{
int ID;
int num;
};

#define LEN sizeof(struct stu) /*LEN 为stu的大小*/

int main(int argc,char *argv[])
{
struct stu stu1,stu2;
stu1.ID = 2;
stu1.num = 3;

char str[LEN];

memcpy(str,&stu1,LEN); /*将stu1保存进str*/

memcpy(&stu2,str,LEN); /*将str转换成stu2*/

printf("%d %d\n",stu2.ID,stu2.num); /*访问stu2仍然得到 2 和 3*/
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

 


说明:str 是一个char *类型的,但是&stu是一个struct stu *类型的,就像我们前面说的那样,他们的“跳跃力”是不一样的,但是memcpy之所以能将它们都接受,就是因为它的参数是(voID *)类型的。在参数传递的时候包容万象,全都接受,这才能体现人家是memcpy()吗,mem是内存,肯定可以不非要按照某种具体类型处理,具体至于还想memcpy的内部怎么处理,看下面:

http://blog.csdn.net/yangbodong22011/article/details/53227560

四:总结

voID *是一种指针类型,常用在函数参数、函数返回值中需要兼容不同指针类型的地方。我们可以将别的类型的指针无需强制类型转换的赋值给voID *类型。也可以将voID *强制类型转换成任何别的指针类型,至于强转的类型是否合理,就需要我们程序员自己控制了。

#include<stdio.h>

int main(int argc,char *argv[])
{
int a = 2;
double b = 2.0;
voID *c; //定义voID *
int *p = &a;
c = p; //将int * 转成voID *,
double *q = (double *)c; //将voID *转成double *
printf("%.f\n",*q);

return 0;
}

 

oID * 为 “不确定类型指针”。
voID *不可以解引用

(1)voID *可以接受任何类型的赋值:
    任何类型的指针都可以直接赋值给voID *型指针,无需进行强制类型转换,相当于voID *包含了其他类型的指针。

  
(2)voID *可以赋值给任何类型的变量
但是需要进行强制转换,应为voID *的范围较大,所以强制转换,使其进行范围缩小。

 


voID *主要使用在函数里,可以接受其他类型的指针,让函数使用起来更加便捷。

voID * 1,不能解引用 2,+ - 运算

结果是不是正确呢?自己试一试吧~

总结

以上是内存溢出为你收集整理的C++ void*解惑全部内容,希望文章能够帮你解决C++ void*解惑所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1222920.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存