一、#define和typedef
1、#define 是宏定义,它只是无意义的字符替代;
书写格式: #define PI 3.14(不能加分号,否则会无条件替代 PI就会被替代成3.14;)
2、typedef则是类型定义,它代表的是这种类型;
书写格式:typedef int a;(它的后面要加分号,它是完整意义的一行代码)
3、两者区别示例:#define a int*
#typedef int* b;
则 a c,d=int *c, int *d;
b e,f =int *e,int f;(
这个只是无意义的字符替代);
二、高级指针
注意:如果有关于高级指针的题目,最重要的就是看优先级,()和[]的优先级一样最高,但是它们的是自左向右的运算方向,所以两个同时出现时,从左往右看,*的优先级要低一些!!!
我们可以从下面的题目中体会这句话实际应用
a. int a() //函数
b. int a[3] //数组
c. int **a() //a是一个函数,函数返回的是二级指针
d. int (*a)() //a是一个指针,它指向一个函数,函数的返回类型为int
e. int (*a)[6] //a是一个数组指针,括号的优先级是最高的,a指向的数组里存放的是6个int型数
f. int *a() //是一个函数,返回类型是int*
g. int **(*a[6])() //a是一个数组,数组里存放的是指针,每个指针指向的是函数,函数的返回二级指针
h. int **a[6] //a是一个数组, 它里面有六个元素,每个元素是二级指针
i. int *(*a)[6] //a是数组指针, 数组里的元素是int*
j. int *(*a())() //a是一个函数,函数的返回类型是指针,指针指向了一个函数,函数的返回类型为int
k. int (**(*a)())() //a是一个指针,指针指向了一个函数,函数返回二级指针,二级指针又指向一个函
//数,函数的返回类型是int
m.int *(*(*(*a)())[6])() //a是一个指针,它指向一个函数,函数的返回类型为指针,指针又指向了一个数
//组,数组里存放的是指针,指针指向了一个函数,函数的返回类型是int*
三、泛型指针
1、NULL
在c中,NULL是 void*,而在c++中,NULL是0;
2、void*——泛型(通用)指针
它是一个不确定的类型,可以作为指向任何数据类型的指针,一般用于储存临时变量。
缺点:(1)、不能解引用
(2)、不能做算术运算,例如++;
3、NULL在c和c++中不同
(1)区别:
通用->特定 特定->通用
c 可以 可以
c++ 不可以 可以
(2)不同原因
本来两个不同类型的指针不能进行赋值运算,但是有了void*可能就会有潜在的隐式赋值的问题:
示例代码:
int *p = NULL;
int a = 10;
char b = 'x';
p = &a;
char *cp = &b;
//cp = &a;//error
void *vp = cp;
p = vp;
int a = 10;
char b = 'x';
p = &a;
char *cp = &b;
//cp = &a;//error
void *vp = cp;
p = vp;
注意:本来cp和p是不能互相转换的 ,由于在c中允许从通用在特定转换,所以利用泛型指针可能就会出现隐式的赋值,出现一些奇怪的问题,所以c++中进行了改善,可以吧c中的void *改成0,但是因为历史原因,如果修改可能会引起一些c语言开发的软件出现问题,牵扯到了一系列的事情,所以就没有更改,但是不能把c++中的NULL改成0,会上面的问题。
四、泛型编程
1、函数指针
int(*p)(int,int); //函数指针
p =& Max; //函数名字就是函数地址
printf("%d\n",(*p)(10,20));
p = Avg;//p =& Avg; //两种赋值方式都可以
printf("%d\n",p(10,20)); //两种方式都可以混用
printf("%d\n",(*p)(10,20));
p =& Max; //函数名字就是函数地址
printf("%d\n",(*p)(10,20));
p = Avg;//p =& Avg; //两种赋值方式都可以
printf("%d\n",p(10,20)); //两种方式都可以混用
printf("%d\n",(*p)(10,20));
2、memcpy()实现
void mymemcpy(void *vp1,void *vp2,int size)
{
char *tmp=(char*)malloc(size);
char *p1=(char *)vp1;
char *p2=(char *)vp2;
{
char *tmp=(char*)malloc(size);
char *p1=(char *)vp1;
char *p2=(char *)vp2;
if((p1
{
for(int i=0;i
{
p1[i]=p2[i];
}
}
{
for(int i=0;i
{
p1[i]=p2[i];
}
}
else
{
for(int i=size-1;i>=0;i--)
{
p1[i]=p2[i];
}
}
}
{
for(int i=size-1;i>=0;i--)
{
p1[i]=p2[i];
}
}
}
3、泛型编程示例
void Swap(void *vp1,void *vp2,int size)
{
void *tmp = malloc(size);
memcpy(tmp,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,tmp,size);
free(tmp);
char *tmp = (char *)malloc(size);
char *cp1 = (char *)vp1;
char *cp2 = (char *)vp2;
int i;
for(i=0;i
{
tmp[i] = cp1[i]; //这一部分是强转之后,一个字节一个字节交换,这样不管是什么类型的数据,只需要根据它
{
void *tmp = malloc(size);
memcpy(tmp,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,tmp,size);
free(tmp);
char *tmp = (char *)malloc(size);
char *cp1 = (char *)vp1;
char *cp2 = (char *)vp2;
int i;
for(i=0;i
{
tmp[i] = cp1[i]; //这一部分是强转之后,一个字节一个字节交换,这样不管是什么类型的数据,只需要根据它
//传过来的单位字节数size就可以进行交换了,可以不用考虑类型。
}
for(i=0;i
{
cp1[i] = cp2[i];
}
}
for(i=0;i
{
cp1[i] = cp2[i];
}
for(i=0;i
{
cp2[i] = tmp[i];
}
free(tmp);
}
{
cp2[i] = tmp[i];
}
free(tmp);
}
void Swap_int(int *p1,int *p2)//普通写法,这个可以解决int类型
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void Swap_float(float *p1,float *p2)//这个可以解决float类型
{
float tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
{
float tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int main(void)
{
int a = 10;
int b = 20;
//Swap_int(&a,&b);
Swap(&a,&b,sizeof(int));
printf("%d,%d\n",a,b);
float c = 12.5f;
float d = 45.5f;
//Swap_float(&c,&d);
Swap(&c,&d,sizeof(float));
printf("%f,%f\n",c,d);
float d = 45.5f;
//Swap_float(&c,&d);
Swap(&c,&d,sizeof(float));
printf("%f,%f\n",c,d);
return 0;
}
}
4、回调函数
这个概念是建立在两个角度,一个是使用者的角度,一个是处理者的角度,使用者调用所给的功能函数解决问题,但是所给范围太过大,所以处理者又把权力交给使用者,让使用者给出详细的规格说明(这里就是指的函数)
代码示例:
typedef struct Student
{
char name[20];
int score;
}Student;
{
char name[20];
int score;
}Student;
typedef int (*PCmp)(void *vp1,void *vp2);
//泛型编程
int Search_int(int *arr,int len,int key)
{
for(int i=0;i
{
if(arr[i] == key)
{
return i;
}
}
return -1;
}
int Search_int(int *arr,int len,int key)
{
for(int i=0;i
{
if(arr[i] == key)
{
return i;
}
}
return -1;
}
//泛型查找
//elemsize单元格大小,
//cmp判断相等的依据,cmp也称为回调函数
int Search(void *arr,int len,void *pkey,int elemsize,PCmp cmp)
{
void *base;
for(int i=0;i
{
base = (char *)arr+i*elemsize;//arr+i
//if(memcmp(base,pkey,elemsize) == 0)//??
if(cmp(base,pkey) == 0)
{
return i;
}
}
return -1;
}
//elemsize单元格大小,
//cmp判断相等的依据,cmp也称为回调函数
int Search(void *arr,int len,void *pkey,int elemsize,PCmp cmp)
{
void *base;
for(int i=0;i
{
base = (char *)arr+i*elemsize;//arr+i
//if(memcmp(base,pkey,elemsize) == 0)//??
if(cmp(base,pkey) == 0)
{
return i;
}
}
return -1;
}
int Cmp_int(void*vp1,void*vp2)
{
return *(int *)vp1 - *(int*)vp2;
}
{
return *(int *)vp1 - *(int*)vp2;
}
#define EPS 0.000001
int Cmp_double(void *vp1,void *vp2)
{
double tmp = *(double *)vp1 - *(double *)vp2;//0.1
if(tmp > EPS)
{
return 1;
}
else if(tmp < -EPS)
{
return -1;
}
else
{
return 0;
}
//0.2 - 0.1
}
int Cmp_double(void *vp1,void *vp2)
{
double tmp = *(double *)vp1 - *(double *)vp2;//0.1
if(tmp > EPS)
{
return 1;
}
else if(tmp < -EPS)
{
return -1;
}
else
{
return 0;
}
//0.2 - 0.1
}
int Cmp_stu_sco(void *vp1,void *vp2)
{
return ((Student *)vp1)->score - *(int *)vp2;
}
{
return ((Student *)vp1)->score - *(int *)vp2;
}
int Cmp_stu_name(void *vp1,void*vp2)
{
return strcmp(((Student *)vp1)->name,(char *)vp2);
}
{
return strcmp(((Student *)vp1)->name,(char *)vp2);
}
int main()
{
{
int arr[10] = {3,7,0,9,67,8,99};
int ikey = 9;
int index1 = Search(arr,10,&ikey,sizeof(int),Cmp_int);
if(index1 >=0 )
{
int ikey = 9;
int index1 = Search(arr,10,&ikey,sizeof(int),Cmp_int);
if(index1 >=0 )
{
printf("%d\n",arr[index1]);
}
else
{
printf("无此数\n");
}
double brr[4] = {12.3,34.5,56.7,78.9};
double dkey = 34.5;
int index2 = Search(brr,4,&dkey,sizeof(double),Cmp_double);
if(index2 >=0 )
{
printf("%f\n",brr[index2]);
}
else
{
printf("无此数\n");
}
Student crr[3] = {"caocao",80,"liubei",30,"sunquan",100};
int nkey = 100;
int index3 = Search(crr,3,&nkey,sizeof(Student),Cmp_stu_sco);
char *name = "liubei";
int index3 = Search(crr,3,name,sizeof(Student),Cmp_stu_name);
Student skey = {"caocao",80};
int index3 = Search(crr,3,&skey,sizeof(Student));
if(index3 >=0 )
{
printf("%s,%d\n",crr[index3].name,crr[index3].score);
}
else
{
printf("无此人\n");
}
return 0;
}
}
else
{
printf("无此数\n");
}
double brr[4] = {12.3,34.5,56.7,78.9};
double dkey = 34.5;
int index2 = Search(brr,4,&dkey,sizeof(double),Cmp_double);
if(index2 >=0 )
{
printf("%f\n",brr[index2]);
}
else
{
printf("无此数\n");
}
Student crr[3] = {"caocao",80,"liubei",30,"sunquan",100};
int nkey = 100;
int index3 = Search(crr,3,&nkey,sizeof(Student),Cmp_stu_sco);
char *name = "liubei";
int index3 = Search(crr,3,name,sizeof(Student),Cmp_stu_name);
Student skey = {"caocao",80};
int index3 = Search(crr,3,&skey,sizeof(Student));
if(index3 >=0 )
{
printf("%s,%d\n",crr[index3].name,crr[index3].score);
}
else
{
printf("无此人\n");
}
return 0;
}