高级指针和泛型编程

来源:互联网 发布:淘宝宝贝主图文字添加 编辑:程序博客网 时间:2024/06/03 15:43
一、#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;
注意:本来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));

2、memcpy()实现
void mymemcpy(void *vp1,void *vp2,int size)
{
 char *tmp=(char*)malloc(size);
 char *p1=(char *)vp1;
 char *p2=(char *)vp2;
 if((p1
 {
  for(int i=0;i
  {
   p1[i]=p2[i];
  }
 }
 else
 {
  
  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];    //这一部分是强转之后,一个字节一个字节交换,这样不管是什么类型的数据,只需要根据它
                              //传过来的单位字节数size就可以进行交换了,可以不用考虑类型。
 }
 for(i=0;i
 {
  cp1[i] = cp2[i];
 }
 for(i=0;i
 {
  cp2[i] = tmp[i];
 }
 free(tmp);
 
 
}
void Swap_int(int *p1,int *p2)//普通写法,这个可以解决int类型
{
 int tmp = *p1;
 *p1 = *p2;
 *p2 = tmp;
}
void Swap_float(float *p1,float *p2)//这个可以解决float类型
{
 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);
 return 0;
}

4、回调函数
这个概念是建立在两个角度,一个是使用者的角度,一个是处理者的角度,使用者调用所给的功能函数解决问题,但是所给范围太过大,所以处理者又把权力交给使用者,让使用者给出详细的规格说明(这里就是指的函数)

代码示例:
typedef struct 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;
}
//泛型查找
//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;
}
#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_stu_sco(void *vp1,void *vp2)
{
 return ((Student *)vp1)->score - *(int *)vp2;
}
int Cmp_stu_name(void *vp1,void*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 )
 {
 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;
}
原创粉丝点击