//void真正发挥的作用在于:
//(1) 对函数返回的限定;
//(2) 对函数参数的限定
// (3)void不能代表一个真实的变量, 凡是试图用它去表示真值得做法都是不合法的
//void的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中“抽象基类”的概念,也很容易理解void数据类型。
//正如不能给抽象基类定义一个实例,我们也不能定义一个void(让我们类比的称void为“抽象数据类型”)变量。
#include<stdio.h>
#include<string.h>
#define ARRSIZE 87
int main()
{
int a = 8;
void *pVoid = a; //定义一个void变量没有意义
int *pInt;
pVoid = pInt; //void *可以指向任何类型的数据,“无类型”可以包容“有类型”
//pInt = pVoid, xxx,而“有类型”则不能包容“无类型”
//如果函数的参数可以是任意类型指针,那么应声明其参数为void *
//典型的如内存操作函数memcpy和memset的函数原型分别为:
//void * memcpy(void *dest, const void *src, size_tlen);
//void * memset ( void * buffer, int c, size_t num );
//这样,任何类型的指针都可以传入memcpy和memset中,memcpy和memset函数返回的也是void *类型.这也真实地体现了内存操作函数的意义
//因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型,这样的memcpy和memset明显不是一个“纯粹的,脱离低级趣味的全能的”函数!
int intArray1[ARRSIZE] = {1, 2, 3};
int intArray2[ARRSIZE] = {4, 5, 6};
memset(intArray1, 0, ARRSIZE*sizeof(int));
printf("intArray1[2] = %d\n", intArray1[2]);
memcpy(intArray2, intArray1, ARRSIZE*sizeof(int));
printf("intArra2[2] = %d\n", intArray2[2]);
float intArray3[ARRSIZE] = {1,23, 2,64, 3,89};
float intArray4[ARRSIZE] = {4.3, 5.7, 6.9};
memset(intArray3, 0, ARRSIZE*sizeof(int));
printf("intArray3[2] = %f\n", intArray3[2]);
memcpy(intArray4, intArray3, ARRSIZE*sizeof(int));
printf("intArray4[2] = %f\n", intArray4[2]);
//对于指针如果暂时没有合适的初始化值,就应该把它置为NULL(0)。
int *p = NULL;
printf("&p = %p\n", &p); //逻辑地址为0x00000000,不可访问,会出现段错误,只适用于指针初始化未能赋值时使用。
printf("pVoid = %d, &pVoid = %p; pInt = %d, &pInt = %p\n", pVoid, &pVoid, pInt, &pInt);
(char *)pVoid++; //ANSI, GNU,ALL RIGHT!
printf("pVoid = %d, &pVoid = %p; pInt = %d, &pInt = %p\n", pVoid, &pVoid, pInt, &pInt);
return 0;
}
#include<stdio.h>
int main()
{
int *p = NULL;
printf("&p = %p\n", &p); //输出地址是随机的
return 0;
}