32位与64位
32位机器是指CPU为32位
CPU是负责:
(2)指令控制(指令位数为32位);
指针地址可存放32位,可以表示4G的寄存器地址
64位机器:
指针地址可存放64位,可以表示pow(2,32)*4G的地址
指针类型的作用:
指针的大小都是4byte(32位机器)
1.指针类型决定了再解引用的时候指针有多大的权限:
int main() { int a=1; int* pa=&a; *pa=2;//此时pa指针让a的值也发生了改变,a=2; } { int a=1; char*pa=&a; *pa=2;//此时pa指针让a的值也改变了,但是a!=2; //因为指针pa的权限只能改变1byte;//类型不同的时候编译器也会报警告 }
2.决定了,指针向前或者向后走一步,走多大距离
如下面,int型加1,地址增加4;char型加1,地址增加1;
野指针
1.指针未初始化
1. void main() 2. { 3. int* p; 4. *p=20;//此时指针p就是野指针 5. }
纠正方法:
1. void main() 2. { 3. int* p=NULL; 4. *p=20; 5. }
2.指针越界访问
void main() { int arr[10]={0}; int* p=arr; for(int i=0;i<=11;i++) { *(p++)=i; }//当指针超出10的范围,i=11时就发生了越界 }
3.指针指向空间释放
int* test() { int a=10; printf("%d\n",a); return &a; }//当&a返回的时候,a销毁了,这时候&a指向的a空间就释放了 void main() { int* p=test();//这时候p就是野指针 *p=100; }
野指针避免方法:
*p=NULL;
一般指针等于 NULL 的就是野指针,在敲代码过程中尽量避免使用野指针
1. if(q!=NULL)使用指针前检查有效性 2. {.....}
1.指针初始化
2.小心指针越界
3.指针指向空间释放及时置空(*p=NULL)
4.避免返回局部变量的地址
5.指针使用前检查有效性
指针运算
1.指针+-整数
指针加减整数所得的结果要看指针类型,而不是字节个数;
2.指针-指针
得到指针和指针之间元素的个数
void main { int arr[10]={0,1,2,3,4,5,6,7,8,9} printf("%d\n",arr[9]-arr[0]);//这时候打印的是9 }
3.指针的关系运算
两个指针可以比较大小
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但不允许与指向第一个元素之前的那个内存位置的指针进项比较(允许向后越,不允许向前越界),大部分编译器都可以运行,但是与向前越界的比较不规范,不建议使用
void main() { int arr[10]={0}; for(int* p=&arr[0];p<&arr[9];) { *++p=0;//先++P,然后*p=0; }//将arr[1]到arr[10]的值变成0; }
数组与指针
数组名是首元素的地址
但是有两个例外:
1.sezeof(数组名),数组名表示整个数组,计算的是整个数组的大小
2.&数组名,数组名表示整个数组,取出的是整个数组的地址
整个数组指针与数组首元素地址不一样:
打印的一样但功能不一样,数组名的指针进行加减时候加减的是整个数组的大小(类型不一样);
数组可以通过指针访问
二级指针
void main() { int a=10; int* pa=&a;// (一级指针),pa是一个指针变量,同样需要四个字节的内存,这个内存也有一个地址 int* * ppa=&pa;// (二级指针) int* * *pppa=&ppa;//(三级指针) }
指针数组
存放指针(地址)的数组就叫指针数组
void main() { int =1,b=2,c=3,d=4; int* arr[4]={&a,&b,&c,&e};//指针数组 }
指针数组的具体用处(可以模拟二维数组):