指针
1、什么是指针
指针才C语言中就是内存单元格的地址
每个内存单元格的大小为1字节
指针变量:用来存放地址的变量
#include<stdio.h>
int main()
{
int a =0;
int* pa =&a;
char* pc=NULL;
printf("%d\n",sizeof(pa));//4
printf("%d\n",sizeof(pc));//1
return 0;
}
//32位系统---32根物理地址线---2^32--00000……(32个0) ---4个字节
9=2^3+2^0=1001(16进制对应二进制是四位)
7=4+2+1=111(八进制对应二进制是三位)
地址在内存中表示是16进制的一种方式
2、指针的类型
不同类型指针大小一样
int main()
{
int* pa;
char* pc;
float* pf;
//不能有通用指针类型,因为是不一样的
printf("%d\n",sizeof(pa));//4
printf("%d\n",sizeof(pc));//4
printf("%d\n",sizeof(pf));//4
int a=0x11223344;
/*int* pa=&a;//int四个字节
*pa=0;*///00 00 00 00
char*pc=&a;//字符类型指针,字符大小一个字节,整型大小四个字节 (char类型一个字节)
*pc=0;//00 33 22 11
//1.指针类型决定了:指针解引用的权限有多大,比如整型为4个字节,则整型指针变量可改变4个字节的内存
//如double类型占8个字节
return 0;
}
int main()
{
int arr[10]={0};
int *pa=arr;
char *pc=arr;
printf("%p\n",pa);//0x11223344
printf("%p\n",pa+1);//0x11223348 因为pa是int类型4个字节,所以加一多4步
printf("%p\n",pc);//0x11223344
printf("%p\n",pc+1);//0x11223345
//2.指针类型决定:指针走一步(+1)能走多远,即指针步长
return 0;
}
指针类型的应用:
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int*pa=arr;
int i=0;
for(i=0;i<10;i++)
{
*(pa+i)=1;//这样整个数组就等于1了
pa+i//一次性跳过4个字节
}
return 0;
}
//3.野指针
指针指向的位置是不可知的情况(随机的,不正确的)
//1.指针未初始化
int main()
{
int* p;//p应该给到明确的地址
*p=20;//所以这样写不对
return 0;
}
//2.指针访问越界
int main()
{
int arr[10]={0};
int* p=arr;
int i=o;
for(i=0;i<=10;i++)
{
*p=i;
p++;//数组地址的累加 相当于上面 *(pa+i)
}
return 0;
}
//3.指针指向空的空间,指针指向的空间被释放
int* test()
{
int a=10;
return &a;
}//局部变量的生命周期是它对应的大括号
int main()
{
int* p=test();//拿到的是a的地址
*p=20;
return 0;
}
int main()
{
int* p=NULL;//定义空指针
int a=1;
p=&a;
}
如何避免野指针
1.指针初始化
int*p = NULL;//不知道指针指向地址是哪里
int*p=&a;//知道指针指向的地址是哪里
2.小心指针越界
3.指针指向空间被释放时,要及时赋值NULL
4.要避免返回(return)局部变量的地址
5.指针使用之前,要检查有效性
int* p=NULL;
p=&a;
if(p!=NULL)//检查指针的有效性
{
}
4.指针的运算
//1.指针+—整数
int main()
{
int arr[10]={9};
int*p=arr;
int i=0;
for(i=9;i>=10;i--)
{
p=p+i;//指针往左右移的问题
}
//2.指针-指针
int arr[10]= {0};
int i=&arr[9]-&arr[0];
printf("%d\n",i);
return 0;
}
//3.指针的关系运算
关系运算:< > >= <= == !=
int a[10]={0};
int* i=NULL;
for(i=&a[9];i>&a[0];)
{
--i =0;
/**i=i-1;
*i=0;*/
*(--i)=0;//i是9的地址,--i是8的地址
}
for(i=&a[9];i>=a[0];i--)
{
*i=0;
}
//标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但是,不允许与指向第一个元素之前的内存位置指针进行比较
5.指针和数组
数组名表示的是数组首元素的地址(两种情况除外)
(1)sizeof(arr)求的是整个数组占内存的大小,sizeof(arr)/sizeof(arr[0])这里数组名并不是地址,这是求几个元素
(2)&arr获得的是整个数组的地址
int arr[10]={0};
sizeof((arr+1)-arr)=4;//就是一个int类型
sizeof(&arr+1)/*跨数组了*/-&arr=40;???????????????
int main()
{
int arr[10]={0;
int* p=arr;p是arr的首元素的地址,指向arr[0]的首地址,但是a[0]的地址指向a[2]的地址
arr[2]=*(p+2);
*(p+2)==*(arr+2);
arr[2]=*(arr+2);
}
void bubble_sort(int arr1[],int sz1)
{
arr1+0==arr+1;
int i=0;
for(i=0;i<sz1-1;i++)
{
int j=0;
for(j=0;j<sz1-i-1;j++)
{
if(arr1[j]>arr1[j+1])
{
int temp=arr1[j];
arr1[j]=arr[j+1];
arr1[j+1]=temp;
}
}
}
}
int main()
{
int arr[]={9,8,7,6,5,4,3,2,1,0};
int sz=sizeof(arr)/sizeof(arr[0]);//数组的长度
bubble_sort(arr,sz);
return 0;
}
6.二级变量
指针,一个变量,也需要地址存放,那么存放指针地址的变量,叫做二级指针
int main()
{
int a=0;
int* pa=&a;
int* *ppa=&pa;
**ppa=&a;//*ppa==pa就是pa=&a
**ppa=20;
就是a=20;
return 0;
}
7.指针数组
int arr[],char arr1[],本质都是数组
指针数组的本质也是数组,指针数组里面的元素是指针类型
int *arr[5]//定义整型数组 里面放的都是指针