void main()//关于指针的扩展理解
{
int ar[10] = {};//ar时整型数组
int a = 1;
int b = 2;
int c = 3;
int *br[10] = { &a, &b, &c };//br不是指针而是一个存放地址的数组
int(*cr)[10]=&ar;//cr是一个存放数组的首指针,cr后面括号的值必须和所存放数组的 大小一样,这是cr+1时,会移动整个数组大小,它的识别能力为整个数组
//int(*xr) = &br;这样无法编译通过,因为在这条语句中xr是一个存放整型数组的指 针,然而br是一个存放地址的数组,所以类型不同
int *(xr)[10]=&br;//xr也是一个指向数组的首地址,但是xr所指的数组是存放地址的
//同理,当qr要指向br时需要加
int *(&qr)[10] = br;
int(&qr)[10] = ar;//引用
//int &cr[10] 这样的写法是错误的,因为引用是不开辟空间的,然而给的方括号中10,又让系统去开辟空间,造成了矛盾
//同理 int &(&cr)[10]自然也无法通过编译
}
下面是函数指针的介绍
int Add(int x, int y)
{
return x + y;
}
int dis(int x, int y)
{
return x - y;
}
int *App(int x,int y)
{
int z = x + y;
return &z;
}
void printdis(int x, int y, int(*pfun)(int, int))//printdis(int x, int y, int pfun(int, int)),这样也是正确的,当函数的声明在形参时,是当做函数指针使用的
{
if (pfun != NULL)
{
int z = (*pfun)(x, y);
cout << z;
}
}
void main2()
{
int pfub(int, int);//是函数声明
int(*pfun)(int, int);//pfun是一个指针,而最前面的int表示所调用函数的返回类型
int *(*pfum)(int, int);//同理int *知识表示调用函数的类型,(*pfun)表示pfun是一个指针
//上面两种方式是定义函数指针的唯一方式
int(*pfun)(int, int) = NULL;//是将pfun的值赋为NULL,而不是将函数的值赋值为NULL;
pfun = Add;//表示将add函数的地址赋值给pfun
int x = 1;
int y = 2;
int z;
int z = (*pfun)(x,y);
pfum = App;
int *p;
p = (*pfum)(x, y);
sizeof(pfun);//结果为4,就是指针的大小
//sizeof(*pfun)是无法计算的,因为无法计算出函数的大小
//同理函数指针pfun+=1也是无法进行的,因为无法计算函数的大小所以也无法用过+1来跳到下一个函数;
printdis(x, y, Add);//这就是函数指针的调用方式,至于函数指针的定义是在printdis函数中进行的
}
//下面的函数内容是使用一个指针,将多个类型的数组进行输出,qsort,bsearch
struct Student
{
char s_id[20];
char s_name[20];
char s_sex;
int s_age;
};
void * PrintInt(void *p)
{
int *s = (int*)p;
printf("%d \n", *s);
return s + 1;
}
void * PrintDouble(void *p)
{
double *s = (double*)p;
printf("%f \n", *s);
return s + 1;
}
void * PrintStudent(void *p)
{
Student *s = (Student *)p;
printf("%s ", s->s_id);
printf("%s ", s->s_name);
printf("%c ", s->s_sex);
printf("%d \n", s->s_age);
return s + 1;
}
void PrintArray(void *ar, int n, void * (*pfun)(void*))
{
if (ar == NULL || n < 1 || pfun == NULL)
return;
for (int i = 0; i<n; ++i)
{
ar = pfun(ar);
}
printf("\n");
}
struct node{
int(*p)(int);
void(*q)(double);
};
int app(int){}
void diss(double){}
int main3()
{
int ar[] = { 12, 23, 34, 45, 56, 67, 78, 90 };
int arlen = sizeof(ar) / sizeof(ar[0]);
double dr[] = { 1.2, 2.3, 3.4, 5.6, 7.8 };
int drlen = sizeof(dr) / sizeof(dr[0]);
Student sr[] = { "201901001", "yhping", 'm', 23,
"201901002", "lilingjie", 'f', 15,
"201901003", "zhanghuan", 'f', 18
};
int studlen = sizeof(sr) / sizeof(sr[0]);
PrintArray(ar, arlen, PrintInt);
PrintArray(dr, drlen, PrintDouble);
PrintArray(sr, studlen, PrintStudent);
int x = 1, y = 2;
int(*pfunm[2])(int, int) = { Add, dis };//用数组的方式来使用函数指针,(*pfunm[2])中的pfunm是一个存放地址的数组不是指针
node n = { app, diss };
int di; //但是使用数组存放函数指针是必须要求每个函数的类型相同
cin >> di; //但是为了是解决这个难题,可以使用结构体来初始化
switch (di)
{
case 0:
cout<<(*pfunm[0])(x, y); break;
case 1:
cout<<(*pfunm[1])(x, y); break;
default:break;
}
return 0;
//如果给出了函数的地址,需要我们调用函数,这是我们需要先将地址给强转为函数指针类型,再调用函数
//比如地址为0x00412db0
//调用的方式为int z = (*(int(*)(int,int)0x00412db0)(x,y)
typedef int(*gun)(int, int);//这是类型声明,不是宏替换,这是gun就是函数指针类型
#define sun int*
sun a, b;//相当于int *a,*b
typedef int *sum;
sum a, b;//也相当于 int *a,*b
//在typedef中*sum就已经说明了他为指针类型,然后经过typedef后确定了他是一个int类型的指针类型
//所以typedef的意义和#define是不同的
}
举一个例题
要求数组指针向下移动,在从数组里面向下移动,输出ar2中的第三个
在这要说明的数组的地址和数组的首元素地址的值是一样的,但是意义不同
在数组的地址前加*号就变为了数组的首元素地址如&ar0是数组的地址,
*&ar就变为了数组首元素的地址
int ar0[4];
int ar1[4];
int ar2[4] = { 1, 2, 4, 5 };
int(*s)[4] = &ar0;
s += 2;
cout<<*(*s+2);
//也可写作
cout<<*(*(s+2)+2);
cout<<*(s[2]+2);
cout<<s[2][2];