一、
指针变量:指向地址的变量
指针就是地址,用来存放地址的变量
变量指针:变量地址
指针是存放地址才出现的,地址是为了标示一块地址空间的。
指针让地址有地方存放,指针让内存的访问更加便捷。
指针的大小子在32位平台是4个字节,在64位平台是8个字节。
二、指针和指针类型
指针是有类型的,类型是:type+*的方式,比如 int* 类型的指针是为了存放 int 类型的地址。
(1)、指针+-整形
#include <stdio.h> #include <windows.h> int main() { int num=10; char *pc=(char *) # int *pi=# printf("%p ",&num);// 0070FE94 printf("%p ",pc); // 0070FE94 printf("%p ",pc+1);// 0070FE95 printf("%p ",pi); // 0070FE94 printf("%p ",pi+1);// 0070FE98 system("pause"); return 0; }
总结:指针的类型决定了指针行前或者向后走一步有多大(距离)。
(2)、指针的解引用
#include <stdio.h> #include <windows.h> int main() { int num = 0x11223344; char *pc = (char *)# int *pi = # *pc = 0x55; *pi = 0; system("pause"); return 0; }
总结:指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字符)
比如:char* 的指针解引用就只能访问一个字节,而int* 的指针的解引用就能访问四个字节。
三、指针数组和数组指针
指针数组:指针数组是数组,是一个存放指针的数组
int *arr1[10];
char *arr2[4];
数组指针:数组指针是指针
int (*p)[10];
数组指针的使用
#include <stdio.h> #include <windows.h> int main() { int arr[10] = { 0 }; //arr 表示数组首元素的地址 //&arr表示数组的地址 printf("%p ", arr); //00EFFC3C printf("%p ", arr + 1); //00EFFC40 printf("%p ", &arr); //00EFFC3C printf("%p ", &arr + 1);//00EFFC64 system("pause"); return 0; }
二维数组传参
void test() { int arr[3][5]; print(arr); } void print(int arr[][5])//可以 void print(int arr[3][5])//可以 void print(int (*arr)[5]) //推荐 void print(int **arr) //不推荐 数组传参降级为指针,指向该内部元素的指针。二维数组降级为一维数组是指针。 一级指针传参 #include <stdio.h> #include <windows.h> void test(int *p,int n) { int i = 0; for (; i < n; i++) { printf("%d ", p[i]);//*(p+i) } } int main() { int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; int *pt = arr; int size = sizeof(arr) / sizeof(arr[0]); test(pt, size); system("pause"); return 0; }
二级指针传参 #include <stdio.h> #include <windows.h> void test(int **ptr) { printf("num=%d ", **ptr); } int main() { int num = 10; int *p = # int **pp = &p; test(pp); test(&p); system("pause"); return 0; }
函数指针
函数指针是指向函数的指针变量,即本质是一个指针变量。
int (*f)(x,y);
指针函数
指针函数是带指针的函数,即本质是一个函数。函数返回类型是某一类型是指针。
类型标识符 *函数名(参数)
int *f(x,y);
首先它是一个函数,函数返回值是一个地址值。函数返回值必须用同类型是指针变量来接受,
也就是说,指针函数一定能有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
表示:
float *fun();
float *p;
p=fun(a);
查看一个月第几周第几天是多少号? #include <stdio.h> #include <windows.h> int *Getdata(int wk,int dy) { static int calendar[5][7]={{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,-1}}; return &calendar[wk-1][dy-1]; } int main() { int wk,dy; do { printf("Enter week(1-5)day(1-7)"); scanf("%d%d",&wk,&dy); }while((wk<1||wk>5)||(dy<1||dy>7)); printf("%d ",*Getdata(wk,dy)); system("pause"); return 0; }
如何辨别指针函数和函数指针
看函数名前的指针 *号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
函数指针数组
即把函数的地址存放到数组中
int (*parr[10])();
转移表(计算器) #include <stdio.h> #include <windows.h> int add(int a,int b) { return a+b; } int sub(int a,int b) { return a-b; } int mul(int a,int b) { return a*b; } int divi(int a,int b) { if(b==0) { printf("div is zero "); } else return a/b; } int main() { int x,y; int input=1; int ret=0; int (*p[5])(int x,int y)={0,add,sub,mul,divi};//转移表 while(input) { printf("************************ "); printf(" 1:add 2:sub "); printf(" 3:mul 4:divi "); printf("************************ "); printf("请选择:"); scanf("%d",&input); if((input<=4&&input>=1)) { printf("请输入操作数:"); scanf("%d%d",&x,&y); ret=(*p[input])(x,y) ; } else printf("输入有错! "); printf("ret=%d ",ret); } system("pause"); return 0; }
指向函数指针数组的指针
指向函数指针数组的指针是一个指针
指针指向一个数组,数组的元素都是函数指针;
#include <stdio.h> #include <windows.h> void test(const char* str) { printf("%s ",str); } int main() { void (*pfun)(const char*)=test;//函数指针pfun; void (*pfunArr[5])(const char* str);//函数指针数组pfunArr; pfunArr[0]=test; void (*(*ppfunArr)[5])(const char*)=&pfunArr;//指向函数指针数组的指针ppfunArr; system("pause"); return 0; }
回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
这有一些大量的示例可以帮助大家理解回调函数https://www.zhihu.com/question/19801131
下面几个例子帮助大家理解
#include <stdio.h> #include <windows.h> int int_cmp(const void *p1,const void *p2) { return (*(int *)p1>*(int *)p2); } void _swap( void *p1, void *p2, int size) { int i=0; for(i=0;i<size;i++) { char tmp=*((char *)p1+i); *((char *)p1+i)=*((char *)p2+i); *((char *)p2+i)=tmp; } } void bubble(void *base,int count,int size,int(*cmp)(void *,void *))//int(*cmp)(void *,void *)回调函数 { int i=0; int j=0; for(;i<count-1;i++) { for(;j<count-1;j++) { if(cmp((char*)base+j*size,(char*)base+(j+1)*size)>0) { _swap((char *)base+j*size,(char*)base+(j+1)*size,size); } } } } int main() { int arr[]={5,1,6,2,3,8,4,9,7}; // char *arr[]={"aaaa","iiii","cccc","bbbb"}; int i; bubble(arr,sizeof(arr)/sizeof(arr[0]),sizeof (int),int_cmp); for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++) { printf("%d ",arr[i]); } printf(" "); system("pause"); return 0; }