指针
指针/地址:每个字节的编号(常量)
指针变量:存储指针的容器(变量)
优点:执行速度快,可读性强,内存的最大特点是选址操作
指针变量存储了指针
指针变量的定义格式
格式:存储类型 数据类型 *指针变量名
*:指针变量说明符,指针的标志
指针变量名:满足命名规范
使用格式:
int* p //p的类型是int*,int表示指针指向地址对应值的类型,表示指针加减运算的偏移量
void* p1 //通用类型指针,可以指向任意类型地址,但需要类型强转
float* p2 //p2+1-->4(字节数)
double* p3 //p3+1-->8
char* p4 //p4+1-->1-
指针变量的定义和初始化
- 指针对应值的类型和变量类型保持一致
int a=100;
int* p1=&a; //指针变量p指向a的地址
float b=3.14;
float* p2=&b;
- 指针对应类型和变量类型不一致
int a=100;
char* p=(char*)&a;
- 可以使用已经初始化的指针为另一个指针初始化
int a=100;
int* p=&a; //p指向a的地址
in * q=p; //q指向p的指向
注意:如果通过p释放a的内存,则q称为悬垂指针
- 不可以直接使用未初始化的指针(野指针)
野指针:非法访问内存
危害:轻则段错误,重则计算机混乱,死机
int* p; //指针p没有指向,计算机会随机指向一片内存
- 当指针不知道指向谁,可以指向NULL
NULL:表示0号地址,该地址内存很小,不可以使用,只能使用指针指向
int* p=NULL;
- 指针只能初始化地址,不能初始化值
int* p=100; //error
面试题
整数,小数,字符,指针和0比较
整数:if(a==0)
小数:if(a>=-0.0000001&&a<=0.0000001)
字符:if(a=='\0')-->if(a==0)
指针:if(p==NULL)-->if(p==0)
解引用和取地址
*的常用功能:乘,说明符,解引用(取地址对应的值)
&的常用功能:逻辑与,按位与,scanf,取地址()
*和&属于逆运算
指针的字节大小
64位操作系统占8字节
32位操作系统占4字节
指针的运算符
指针常见的运算符:算数,关系,赋值
- 算数运算
两个指针做减法得到中间所差字符的个数
+ | p+n | 表示指针向高地址方向偏移了n倍的数据类型字节大小(4n) |
*(p+n) | 表示指针向高地址方向偏移了n倍的数据类型字节大小(4n),再取值(越界) | |
*p+n | 先取p地址对应的值,再对值加n | |
&a+n | 表示指针向高地址方向偏移了n倍的数据类型字节大小(4n) | |
- | p-n | 表示指针向低地址方向偏移了n倍的数据类型字节大小(4n) |
*(p-n) | 表示指针向低地址方向偏移了n倍的数据类型字节大小(4n),再取值(越界) | |
*p-n | 先取p地址对应的值,再对值加n | |
&a-n | 表示指针向低地址方向偏移了n倍的数据类型字节大小(4n) | |
++ | p++ | 先运算,后自增,向高地址方向偏移了一个的数据类型字节大小(4) |
++p | 先自增,后运算,表示向高地址方向偏移了一个的数据类型字节大小(4) | |
++*p | 先取p地址对应的值,再对值自增1 | |
*++p | 先向高地址方向偏移了一个的数据类型字节大小(4),再取值 | |
(*p)++ | 先取值,再运算,最后对值自增1 | |
*p++ | 先p++,再对p进行取值,最后对p自增 | |
*(p++) | 同*p++ | |
-- |
- 关系运算
一般关系运算多用于数组地址连续的情况
> | p>q | 条件成立返回1,不成立返回0 |
>= | p>=q | 条件成立返回1,不成立返回0 |
< | p<q | 条件成立返回1,不成立返回0 |
<= | p<=q | 条件成立返回1,不成立返回0 |
== | p==q | 条件成立返回1,不成立返回0 |
!= | p!=q | 条件成立返回1,不成立返回0 |
- 赋值运算
= | int* p=&a | 指针p指向了a的地址,’=‘的右边可以是变量,常量,表达式,但是左边只能是变量,注意类型一致 |
+= | p+=n | p向高地址方向偏移了n倍的数据类型字节大小(4n) |
-= | p-=n | p向低地址方向偏移了n倍的数据类型字节大小(4n) |
练习
定义字符串赋值为hello,使用指针实现字符串的逆置
一维数组和指针
格式:
int arr[]={11,22,33};
int* p=arr;
&p:指针的地址首编号
总结:
&arr[0]--->p--->&arr---&p[0] //偏移一个元素
&arr //偏移整个数组
&p //偏移整个指针
*(a+1)=2 *(ptr-1)5
ptr[-1]=4 *ptr2=0x02000000
总结
值:arr[i]--->*(&arr[0]+i)--->*(arr+i)--->p[i]--->*(&p[0]+i)--->*(p+i)--->*p++
地址:&arr[i]--->&arr[0]+i--->arr+i--->&p[i]--->&p[0]+i--->p+i--->p++
练习
在主函数中定义一个数组并输入,在自定义函数中求最大值并返回(指针)
在主函数中定义数组并输入,在自定义函数中实现简单选择排序(指针)
值传递和地址传递
值传递:传递的是值,形参的改变不影响实参,形参和实参分别占有存储空间
地址传递:传递的是地址,形参的改变影响实参,形参和实参共享存储空间
练习
请回答下三个程序的ab结果分别是
a=1 b=2值传递
a=2 b=1地址传递
a=1 b=2