指针
是一种数据类型 用来指向一个变量的地址
int a=10; a=20; int b=100; int* p= &a; p=&b; printf("%p ",&b);//%p表示指针 0x7ffee5633874 //printf("%X ",p);//p是一个地址,%X 16进制输出 cout<<p;//0x7ffee5633874
p是int*类型的,*p代表p地址的值,p代表着一个地址
通过指针修改变量的值
*p=200; printf("%d ",b);//200 printf("%d ",*p);//200
sizeof()指针类型在内存中的大小
在64(32)位的机器里,无论什么类型的指针大小都是8(4)个字节,因为存的都是地址,内存地址都是无符号整型的。
cout<< sizeof(p)<<endl;//8 cout<< sizeof(double*)<<endl;//8 cout<< sizeof(short*)<<endl;//8 cout<< sizeof(int*)<<endl;//8 cout<< sizeof(char*)<<endl;//8 cout<< sizeof(float*)<<endl;//8
野指针
是指向一个未知的内存空间,可能在读写的时候发生错误
指针变量也是变量,是变量就可以任意赋值,不要越界即可(64位机器 为8字节)
但是,任意数值赋值给指针变量没有意义,因为任意数值的地址可能时未知的(操作系统不允许操作此指针指向的内存区域),野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。
int a=10; int* p=&a; //指向内存编号为0xff00的内存地址 //内存0-255是系统保留的,不能读,也不能写 p=0xff00;//该地址是未知的内容空间 *p=100; printf("%d ",*p);
空指针
就是指向内存编号为0 的空间,操作该内存空间会报错,一般情况空指针用于条件判断
int* p; p=NULL; *p=100; printf("%d ",*p); if(p!=NULL) { //free(); }
万能指针
int a=10; void* p=&a; *(int *)p=100;//将p强转成int*类型 再在前面加上*,就是取出p地址指向的值 ;再赋值,改变a的值 cout<<a;//100 //cout<<*p;//这样写不行,因为p还是void*类型 cout<<*(int*)p;//100
int arr[10]={0}; void* p=arr; *(int*)p=100; *((int*)p+4)=200; cout<<arr[0]<<" "<<arr[4];//100 200
const修饰指针
1.通过指针修改const修饰的常量
方法是:把常量的地址给指针,通过修改指针的值,来改变常量的值
const int a=10;
printf("%d
",a);//10
int* p=(int*)&a;//将const int*转换为int* 否则报错
*p=100;
printf("%d
",a);//100
printf("%d
",*p);//100
2.如果const修饰int*不能改变指针变量指向的内存地址的值,但是可以改变指针指向的地址
int a=10,b=100; printf("%d ",a);//10 const int* p; p=&a; //*p=100;//不能改变指针变量指向的内存地址的值 因为*p被const修饰着 p=&b;//但是可以改变指针指向的地址 printf("%d ",*p);//100
3.const修饰指针变量 能改变指针变量指向地址的值 但不能改变指针指向的地址
int a=10,b=100; int *const p=&a; //p=&b;//不能改变p的地址值 因为p被const修饰着 *p=100; printf("%d ",*p);//100
4.const修饰指针类型也修饰指针变量 那么不能通过一级指针改变指针指向的地址,也不能通过一级指针修改指针指向的值
用二级指针可以修改
int a=10; int b=20; const int* const p=&a; //p=&b; //*p=100; printf("%d ",*p);
意思就是不能改变const后面修饰的东西的值
指针和数组、指针运算
数组名是数组的首地址 这是一个常量 arr==&arr[0]
1.指向数组的指针 当操作指针的时候,间接操作了数组
int arr[10]={0}; printf("%p ",arr); printf("%p ",&arr[0]); //p=arr;[数据类型*] 变量名 int* p=arr; for(int i=0;i<10;i++) { printf("%d ", p[i]); printf("%d ",*(p+i)); }
数组名和指针的区别:
数组名通过sizeof可以求出数组的大小,指针只包含数组的首地址信息
int arr[10]={0}; int* p=arr; cout<<sizeof(arr);//40=10*(4字节) cout<<sizeof(p);//4
指针实现冒泡排序
void bubble(int* p,int len) { for(int i=0;i<len-1;i++) { for(int j=0;j<len-i-1;j++) { if(*(p+j)>*(p+j+1)) swap(*(p+j),*(p+j+1)); } } } int main() { int arr[10]={0,7,8,1,25,4,2,9,5,3}; int* p=arr; bubble(p,10); for(int i=0;i<10;i++) cout<<*(p+i)<<" "; return 0; }
用指针实现字符串翻转
void rev(char* arr) { int len=strlen(arr); char* p1=arr; char* p2=&arr[len-1]; while (p1<p2) { char temp=*p1; *p1=*p2; *p2=temp; p1++; p2--; } } int main() { char c[10],d; int i=0; while ((d=getchar())!=' '){ c[i++]=d; } rev(c); printf("%s",c); return 0; }
指针数组
int a=10; int b=20; int c=30; int* arr[]={&a,&b,&c}; //arr[0]==&a;arr[1]==&b;arr[2]==&c; printf("%d ",*arr[0]);//10 注意:[]的优先级大于* 所以不用写成*(arr[0]) *arr[2]=200; printf("%d ",c);//200 通过指针数组修改值
char* arr[]={"hello","www","com"}; printf("%c ",*arr[0]);//"hello" printf("%c ",*arr[1]);//"www" printf("%c ",*(arr[0]+1));//"hello"中e
多级指针
int a=10; int* p=&a;//一级指针存的是a的地址,*p代表a的值 int**pp=&p; *pp=&a; **pp=20;//二级指针存的是一级指针的地址 **pp代表一级指针的值 int***ppp=&pp;//三级指针存的是二级指针的地址 **ppp存的是二级指针的值 //*ppp==pp==&p; //**ppp==*pp==p=&a; //***ppp==**pp==*p==a;//多级指针以此类推