指针
- 在32位的机器上,1个指针变量的大小是4个字节,与指针的类型无关
- 在64位的机器上,1个指针变量的大小是8个字节
指针和指针类型
指针的解引用
指针类型决定了指针进行解引用操作的时候能够访问的空间大小
举例:
int a = 0x11223344;
int* pa = &a;
*pa = 0;//会把a的内容全部改为0,即四个字节全是0,即 00 00 00 00
-------------------------------
char* pc = &a;
*pc = 0;
//只会修改a的内容中的一个字节,即 00 33 22 11
int* :4个字节
char* :1个字节
double* :8个字节
指针+-整数
指针类型决定了加减整数时指针走多远,即指针的步长
举例:
int a = 0x11223344;
int* pa = &a;
char* pc = &a;
printf("%p\n",pa);
printf("%p\n",pa+1);
//+4个字节,即一个整型
printf("%p\n",pc);
printf("%p\n",pc+1);
//+1个字节,即一个字符型
举例2
将数组中所有元素改为1
#include<stdio.h>
int main()
{
int arr[10] = {0};//此时的arr: 0 0 0 0 0 0 0 0 0 0
int i;
int* p = arr;//arr即代表数组首地址,不用再使用取地址符号
for(i=0;i<10;i++)
{
*(p+i) = 1; //修改每一个内存空间里的值为1 此时的arr: 1 1 1 1 1 1 1 1 1 1
}
for(i=0;i<10;i++)
printf("%d ",arr[i]);
return 0;
}
野指针
概念:指针指向的位置时不可知的
出现原因:
- 指针未初始化,默认为随机值
- 指针越界访问
int arr[10] = {0};
int* p = arr;
int i = 0;
for(i=0;i<12;i++)
{
p++; //p最后会越出arr的范围,则当指针指向的范围超出arr的范围时,P就是野指针
}
- 指针指向的内存空间已经被释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();// p确实接收到了test()返回的地址,但是该地址空间在test()返回给main()之后就已经被销毁
*p = 20;
return 0;
}
如何规避野指针
-
要初始化
-
小心指针越界
-
若指针指向的空间释放,即不再需要该指针时,就要使指针置NULL,以后不能再访问这个地址。也不再能对这个地址进行修改
-
使用指针之前检查有效性
指针运算
- 指针 + - 整数
- 指针 - 指针
- 指针的关系运算(比较大小)
指针 + - 整数
int* p;
*p ++=0;
先查看++,再解引用
此处++为后置++,则解引用的还是p,然后再对指针++;
指针 - 指针
得到的结果是两个地址中间的元素个数
指针的关系运算
标准允许指针与该数组最后一个元素的地址比较,但不允许和数组的第一个元素的地址比较
指针和数组
数组名是数组首元素的地址,例外:
- &arr,即&数组名--数组名表示整个数组---&数组名表示的是整个数组的地址
- sizeof(arr),即sizeof(数组名),数组名表示的是整个数组,sizeof(数组名)表示的是整个数组的大小
int arr[10] = {0};
printf("%p\n",arr);//A
printf("%p\n",arr+1);//A’
printf("%p\n",&arr[0]);//B
printf("%p\n",&arr[0]+1);//B‘
printf("%p\n",&arr);//C
printf("%p\n",&arr+1);//C’
//A和B意义相同,代表首元素的地址;C代表整个数组的地址
//A'和B'是在原来的基础上加4,C'在原来的基础上加了4*10
通过指针来访问数组
int main()
{
int arr[10] = {0};
int* p = arr;
int i = 0;
//for(i=0;i<10;i++)
//{
//printf("%p=====%p\n",p+i,&arr[i]);//可检验通过指针访问数组和下标访问数组结果相同
//}
for(i=0;i<10;i++)
{
*(p+i) = i;
}
for(i=0;i<10;i++)
{
printf("%d ",arr[i]);
//printf("%d",*(p+i));
}
return 0;
}
二级指针
一级指针的地址
类型: int**
int a = 10;
int* pa = &a;
int ** ppa = &pa;// ppa即为二级指针
二级指针所占内存空间里存储的是一级指针的地址,二级指针所指向的对象的类型是一级指针
实际理解:
int * pa; // *代表pa是指针,int代表pa指向的对象的类型是int型
int* * ppa;//*代表ppa是指针,int*代表ppa指向的对象的类型是int*
int** * pppa;//……
具体应用
printf("%d",**ppa);//即可以打印a
**ppa = 20;
printf("%d",a);//将a的值改为20然后打印
指针数组
数组指针本质上是指针
指针数组
存放指针的数组
应用
int main()
{
int a = 1;
int b = 2;
int c = 3;
int* p[3]={&a,&b,&c};//指针数组
int i = 0;
for(I=0;i<3;i++)
{
printf("%d ",*(p[i]));
}
return 0;
}
其他
- 数组作为参数传递给函数时,要么写 A(int* arr); 要么写A(int arr[] );