指针是一个变量,其值为另外一个变量的地址,即内存位置的直接地址,就像其余变量或常量同样,在使用指针存储其余变量地址以前,对其进行声明,指针变量声明的通常形式为编程
int *ip;//一个整型的指针 double *dp;//一个double型的指针 float *fp;//一个浮点型的指针 char *ch;//一个字符型指针
void main(){ int num=1; //定义一个指针变量,指针 //说明 //1.int *表示类型为指针类型 //2.名称ptr,ptr就是一个int *类型 //3.ptr指向了一个int类型变量的地址 int *ptr=# //num的地址是多少 //说明1:若是要输出一个变量的地址,使用格式是%p //说明2:&num表示取出num这个变量对应地址 printf("num的值=%d num地址=%p",num,&num); //指针变量自己也有地址&ptr //指针变量存放的地址*ptr //获取指针指向的值*ptr printf("ptr的地址是%p ptr存放的值是一个地址为%p ptr指向的值=%d",&ptr,ptr,*ptr); gatchar(); }
指针是一个用数值表示的地址,能够对指针执行算数运算,能够对指针进行四种算数运算:++,--,+,-数组
#include <stdio.h> const int MAX=3;//常量 int main(){ int var[]={10,100,200}; int i,*ptr;//ptr 是一个int *指针 ptr =var;//ptr指向了var数组的首地址 for(i=0;i<MAX;i++){ printf("var[%d]地址=%p",i,ptr); printf("存储值:var[%d]=%d",i,*ptr); ptr++;//ptr=ptr+1(一个int字节数);ptr存放值+4字节 } getchar(); return 0; }
#include <stdio.h> const int MAX=3; int main(){ int var[]={10,100,200}; int i,*ptr; //指针中最后 一个元素的地址 ptr=&var[Max-1]; for(i=MAX;i>0;i++){ //反向遍历 printf("ptr存放的地址=%p",ptr); printf("存储值:var[%d]=%d",i-1,*ptr); ptr--; } getchar(); return 0; }
#include <stdio.h> int main(){ int var[]={10,20,100}; int i,*ptr; ptr=var; ptr+=2;//ptr的存储地址+2个字节 printf("var[2]=%d var[2]的地址 ptr存储的地址=%p ptr指向的值=%d",var[2],&var[2],ptr,*ptr); getchar(); return 0; }
int main(){ int var[]={10,100,200,400,8,12}; int i,*ptr; ptr=&var[2]; ptr-=2; printf("ptr指向的值=%d",*ptr); getchar(); return 0; }
指针能够用关系运算符进行比较,如==,<<=,>>=若是p1和p2指向两个变量,好比同一个数组中的不一样元素,则可对p1和p2进行大小比较dom
#include<stdio.h> int main(){ int var[]={10,100,200}; int* ptr; ptr=var; if(ptr==var[0]){ printf("ok");//错误,类型不同 } if(ptr==&var[0]){ printf("ok2"); } if(ptr===var){ printf("ok3"); } if(ptr>=&var[1]){ printf("ok4"); } getchar(); return 0; }
#include<stdio.h> const int MAX = 3; int main(){ int var[]={10,100,200}; int i,*ptr; ptr=var; i=0; while(ptr<=&var[MAX-2]){ printf("address of var[%d]=%p",i,ptr); printf("value of var[%d]=%d",i,*ptr); ptr++; i++; } getchar(); return 0; }
要让数组的元素指向int或者其余数据类型的地址(指针)。可使用指针数组函数
数据类型 *指针数组名[大小];布局
#include<stdio.h> const int MAX=3; int main(){ int var[]={10,100,200}; int i,*ptr[3]; for(i=0;i<MAX;i++){ ptr[i]=&var[i];//赋值为整数的地址 } for(i=0;i<MAX;i++){ printf("value of var[%d]=%d ptr[%d]自己的地址=%p",i,*ptr[i],i,&ptr[i]); } getchar(); return 0; }
#include <stdio.h> void main(){ //定义一个指针数组,该数组的每一个元素,指向的是一个字符串 char *bookd[]={ "三国演义" "西游记" "红楼梦" "水浒传" }; char *pStr="abc"; int i,len; for(i=0;i<len;i++){ printf("books[%d]指向字符串是=%s pStr指向的内容=%s",i,books[i],pStr); } getchar(); }
address --------------->address--------------->value指针
pointer--------------------pointer------------------variablecode
一个指向指针的指针变量必须以下声明,即在变量名前放置两个星号。例如,下面声明了一个指向int类型指针的指针对象
当一个目标值被一个指针简介指向另外一个指针时,访问这个值须要使用两个星号运算符,好比**ptrip
案例演示内存
#include<stdio.h> int main(){ int var; int *ptr;//一级指针 int **pptr;//二级指针 int ***ppptr;//三级指针 var =3000; ptr=&var;//var变量的地址赋给ptr pptr=&ptr;//将ptr存放的地址赋给pptr ppptr=&pptr;//表示将pptr存放的地址赋给ppptr printf("var的地址=%p var=%d ",&var,var); printf("ptr的自己的地址=%p ptr存放的地址=%p *ptr=%d",&ptr,ptr,*ptr); printf("pptr自己的地址=%p pptr存放的地址=%p **ptr=%d",&pptr,pptr,**pptr); printf("ppptr自己地址=%p ppptr存放的地址 ***ppptr=%d",&ppptr,ppptr,***ppptr); getchar(); rerurn 0; }
当函数的形参类型是指针类型时,是使用该函数时,须要传递指针,或者地址,或者数组给该形参
#include<stdio.h> void test(int *p);//函数声明,接收int* void main(){ int num=90; int *p=# //将num的地址赋给P test2(&num);//传地址 printf("main()中的num=%d",num); test2(p); printf("main()中的num=%d",num); getchar(); } void test2(int *p){ *p+=1;//*p就是访问num的值 }
数组名自己就表明数组首地址,所以传数组的本质就是传地址
#include<stdio.h> double getAverage(int *arr,int size);//函数声明 double getAverage2(int *arr,int size); int main(){ int balance[5]={1000,2,3,17,40}; double avg; //传递一个指向数组的指针做为参数 avg=getAverage(balance,5); printf("Average value is:%f",avg); getchar(); return 0; } //说明:arr是一个指针 double getAverage(int *arr,int size){ int i,sum=0; double avg; for(i=0;i<size;i++){ //arr[0]=arr+0; //arr[1]=arr+一个字节 //arr[2]=arr+2个int 字节 sum+=arr[1]; printf("arr存放的地址=%p",arr); } avg=(double)sum/size; return avg; } double getAverage2(int *arr,int size){ int i,sum=0; double avg; for(i=0;i<size;++i){ sum+=*arr; printf("arr存放的地址=%p",arr); arr++;//指针的++运算,会对arr存放的地址作修改 } avg=(double)sum/size; return avg; }
C语言容许函数的返回值是一个指针(地址),这样的函数称为指针函数
//请编写一个函数strlong(),返回两个字符串中较长的一个 #include<stdio.h> #include<string.h> char *strlong(char *str1,char *str2){ //函数返回的char*(指针) printf("str1的长度%d str2的长度%d",strlen(str1),strlen(str2)); if(strlen(str1)>=strlen(str2)){ return str1; }else{ return str2; } } int main(){ char str1[30],str2[30],*str;//str是一个指针类型,指向一个字符串 printf("请输入第一个字符串"); gets(str1); printf("请输入第二个字符串"); gets(str2); str=strlong(str1,str2); pritnf("longer string :%s",str); getchar(); return 0; }
#include <stdio.h> int *fun(){ //int n=100;//局部变量,在func返回时,就会销毁 static int n=100;//若是这个局部变量是static性质的,那么n存放数据的空间在静态数据区 return &n; } int main(){ int *p=func(); int n; printf("okook");//多是使用到局部变量int n=100占用空间 printf("okoook"); printf("okoook"); n=*p; printf("value =%d",n); getchar(); return 0; }
编写一个函数,他会生成10个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回他们
#include<stdio.h> #include<stdlib.h> //编写一个函数,返回一个一位数组 int *f1(){ static int arr[10];//必须加上static,让arr的空间在静态数据区分配 int i=0; for(i=0;i<10;i++){ arr[i]=rand(); } return arr; } void main(){ int *p; int i; p=f1(); //p指向是在f1生成的数组的首地址(即第一个元素的地址) for(i=0;i<10;i++){ printf("%d",*(p+i)); } getchar(); }
return type(*pointerName)(param list);
用函数指针来实现对函数的调用,返回两个整数中的最大值
#include<stdio.h> //说明 //max 函数 //接收两个Int,返回较大数 int max(int a,int b){ return a>b?a:b; } int main(){ int x,y,maxVal; //说明:函数指针 //1.函数指针的名字 pmax //2.int 表示该函数指针指向的函数是返回int类型 //3.(int,int)表示该函数指针指向的函数形参是接收两个int //4.在定义函数指针时,也能够写上形参名 int(*pmax)(int x,int y)=max int(*pmax)(int,int)=max; printf("Input two numbers:"); scanf("%d %d",&x,&y); //(*pmax)(x,y)经过函数指针去调用函数max maxVal=(*pmax)(x,y); printf("max value:%d pmax=%p pmax自己的地址=%p",maxVal,pmax,&pmax); getchar(); getchar(); return 0; }
使用回调函数的方式,给一个整型数组int arr[10]赋10个随机数
#include<stdio.h> #include<stdlib.h> //回调函数 //1.int (*f)(void) //2.f就是函数指针,它能够接收的函数是(返回int,没有形参的函数) //3.f在这里被initArray调用,充当了回调函数角色 void initArray(int *array,int arrSize,int (*f)(void)){ int i; for(i=0;i<arraySize;i++){ array[i]=f();//经过函数指针调用看getNextRandomValue函数 } } //获取随机值 int getNextRandomValue(void){ return rand();//rand系统函数,会返回一个随机整数 } int main(void){ int myarray[10]; //说明 //1.调用initArray函数 //2.传入了一个函数名getNextRandomValue(地址),须要使用函数指针接收 initArray(myarray,10,getNextRandomValue); //输出赋值后的数组 for(i=0;i<10;i++){ printf("%d",myarray[i]); } printf("\n"); getchar(); return 0; }
#include<stdio.h> void main(){ int *p=null; int num=34; p=# printf("*p=%d",*p); getchar(); }
头文件#include<stdlib.h>声明了四个关于动态内存分配的函数
函数原型void *malloc(unsigned int size) //memory allocation
函数原型 void *calloc(unsigned n,unsigned size)
函数原型void free(void *p)
函数原型 void *realloc(void *p,unsigned int size)
返回类型说明-
int a=3; //定义a 为整型变量 int *p=&a;//p1指向int型变量 char *p2;//p2指向char型变量 void *p3;//p3为无类型指针变量(基类型为void类型) p3=(void *)p1;//将p1的值转换为void *类型,而后赋值给p3 p2=(cahr *)p3;//将p3的值转换为char *类型,而后赋值给p2 printf("%d",*p1);//合法,输出a的值 p3=&a;printf("%d",*p3);//错误,p3是无指向的,不能指向a
说明:当把void 指针赋值给不一样基类型的指针变量(或相反时),编译系统会自动进行转换,没必要用户本身进行强制转换,例如:p3=&a;
至关于“p3=(void )&a;"赋值后获得p3的纯地址,但并不指向a,不能经过 *p3输出a的值
#include<stdio.h> #include<stdio.h> int main(){ void check(int *); int *p,i; //在堆区开辟一个5*4的空间,并将地址(void *),转成(int *),赋给p p=(int *)malloc(5*sizeof(int)); for(i=0;i<5;i++){ scanf("%d",p+i); } check(p); free(p);//销毁堆区p指向的空间 getchar(); getchar(); return 0; } void check(int *p){ int i; printf("不及格的成绩有:"); for(i=0;i<5;i++){ if(p[i]<60){ printf("%d",p[i]); } } }
避免分配大量的小内存块,分配堆上的内存有一些系统开销,因此分配许多小的内存块比分配几个大内存块的系统开销大
仅在须要时分配内存,只要使用完堆上的内存块,就须要即便释放它(若是使用动态分配内存,须要遵照原则:谁分配,谁释放),不然可能出现内存泄露
老是确保释放以分配的内存,在编写分配内存的代码时,就要肯定在代码的什么地方释放内存
在释放内存以前,确保不会无心中覆盖堆上已经分配的内存地址,不然程序就会出现内存泄漏,在循环中分配内存时,要特别当心
指针使用一览
变量定义 类型表示 含义 int i; int 定义整型变量 int *p; int * 定义p为指向整型数据的指针变量 int a[5] int[5] 定义整型数组a,它有5个元素 int *p[4]; int *[4] 定义指针数组p,它由4个指向整型数据的指针元素组成 int (*p)[4] int(*)[4] p为指向包含4个元素的一维数组的指针变量 int f() int() f为返回整型函数值的函数 int *p() int *() p为返回一个指针的函数,该指针指向整型数据 int (*p)() int (*)() p为指向函数的指针,该函数返回一个整型值 int **p; int ** p是一个指针变量,它指向一个整型数据发指针变量 void *p void * p是一个指针变量,基类型为void(空类型),不指向具体的对象