1.指针是什么
指针是用来存放地址的
指针的大小在32位平台是4个字节,在64位平台是8个字节。
指针的声明形式为: type*var_name;
type是指针类型
var_name是指针变量名称,在该语句中*用来指定一个变量是指针。
2.指针变量是什么
- 指针变量是用来存放地址的变量
- &为取地址操作符
- 指针写法注意事项
int*p=&a 正确
*p=&a 错误
原因:*p=&a; 这一句是对(*p)进行赋值操作,(*p)的数据类型是int型,而&a的数据类型是int星,两者类型不同,无法进行赋值,所以语句是错的
3.指针类型有哪些
- 类型
int*p1=NULL;
char*p2=NULL;
short*p3=NULL;
long*p4=NULL;
float*p5=NULL;
double*p6=NULL;里插入代码片
指针类型决定指针走的一步有多大,但是各个类型的指针对应指针的值都是一个代表内存地址的长的十六进制数。
2.指针赋值
指针的赋值前提是相同的指针类型
举例:
intp=1 错误
intp=(int*)1 正确
3.指针类型之间的区别
指针的每一次递增,它其实会指向下一个元素的存储单元。指针的每一次递减,它都会指向前一个元素的存储单元。指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型
#include<stdio.h>
int main()
{
int n = 1;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
该代码运行结果为
000000000062FE0C
000000000062FE0C
000000000062FE0D
000000000062FE0C
000000000062FE10
标题4.指针的强制类型转换
可以转换的原因:所有的指针所占的空间大小都是4字节,只是声明的类型不同,他们的值都是地址指向某个东西,对与机器来说没有本质区别。
以int型转化为float型为例
int n=1;
int*p1=&n;
char*p2=(float*)p1;
5.指针运算
1.指针与整数
指针的每一次递增,它其实会指向下一个元素的存储单元。指针的每一次递减,它都会指向前一个元素的存储单元。指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型,与标题4-3内容相似。(char一个字节 int、float4个字节、double8个字节)
2.指针-指针
求差的两个指针分蘖指向同一个数组的不同元素,通过减法个算出两元素之间的距离。差值的单位与数组类型单位相同
以下例子可理解指针与整数和指针与指针的运算
#include<stdio.h>
int main(){
int a[5]={1,2,3,4,5};
int *p1,*p2,*p3,*p4,*p5;
p1=a;
p2=&a[2];
p3=p1+1;
p4=p2-1;
printf("p1=%p,p3=%p,*p3=%d\n",p1,p3,*p3);
printf("p2=%p,p4=%p,*p4=%d\n",p1,p2,*p4);
printf("%d\n",p3-p4);
return 0;
}
结果为
p1=000000000062FDE0,p3=000000000062FDE4,*p3=2
p2=000000000062FDE0,p4=000000000062FDE8,*p4=2
0
注意:a.若该代码改为
#include<stdio.h>
int main(){
int a[5]={1,2,3,4,5};
int *p1,*p2,*p3,*p4,*p5;
p1=a;
p2=&a[2];
p3=p1+1;
p4=p2-1;
printf("p1=%p,p3=%p,p3=%d\n",p1,p3,p3);
printf("p2=%p,p4=%p,p4=%d\n",p1,p2,p4);
printf("%d\n",p3-p4);
return 0;
}
则结果为
p1=000000000062FDE0,p3=000000000062FDE4,p3=6487524
p2=000000000062FDE0,p4=000000000062FDE8,p4=6487524
0
不同原因:
p是一个指针变量,它存储了一个内存地址。我们可以使用p来访问这个地址的值,例如*p表示该地址处的值。在赋值时,我们可以将另一个地址的值赋给p,例如p = &x表示将变量x的地址赋给p。*p是指针变量p所指向的内存地址处存储的值。也就是说,*p表示p指向的内存单元中的值。
注意:b.指针+指针无意义
3.指针的关系运算
即指针与指针之间比较大小
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
6.指针与数组
1.指针访问数组
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;
p存放的是数组首元素的地址,既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i<sz; i++)
{
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
}
return 0;
}
结果:
可知p+i
其实计算的是数组 arr 下标为i的地址
指针访问数组举例:
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i<sz; i++)
{
printf("%d",*(p++));
}
return 0;
}
结果: 1234567890
2…指针数组
指针数组如int* arr3[5]
arr3是一个数组,有五个元素,每个元素是一个整形指针
指针数组是数组,数组内容存放的是指针
注意:优先级顺序:()> [ ] >*
3.数组指针如int(*p) arr3[5]
数组指针是指针指向数组
7.指针的解引用
解引用是返回内存地址中对应的对象
比如
int a=10;
int *p=&a;
cout<<*p<<endl;
输出a的值,就是解引用操作
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
8.野指针
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1.成因:指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
2.指针越界访问
#include <stdio.h>
int main()
{
int arr[5]={1}
int *p=arr;//局部变量指针未初始化,默认为随机值
int i=0
for(i=0;i<10;i++) {
*(p++)=arr[i];
}
return 0;
}
当指针指向的范围超出数组arr的范围时,p就是野指针
9.二级、多级指针
举例二级指针int*ppa,多级指针如是类似写法
int a=5
int*pa=&a;
int **ppa=&pa
int***pppa=&ppa
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .