C语言 - 初阶指针
- 一 指针概念
- 注意:
- 指针变量的大小:(与指向的数据类型无关)
- 二 指针类型
- 2.1指针类型的含义:
- 2.1.1 不同指针类型决定解引用时候权限不同:
- 总结:
- 2.1.2 任何类型的指针变量都能存放地址(即使跨类型)
- 三 野指针(非法的指针):
- 3.1 可能出现野指针的情况:
- (1) 指针未初始化:指针里面是一个随机值,解引用会造成非法访问内存
- (2) 指针越界:
- 3.2 如何避免野指针:
- 四 指针运算:
- 4.1 指针+-整数:
- 4.2 指针-指针:
- 五 数组和指针之间的关系
- 六 二级指针:
- 七 指针数组:存放指针的数组(本质上是数组)
- 其他:
一 指针概念
内存单元都有对应的编号----这个编号就称为地址(地址能够找到内存单元,形象称指针)
两层含义:
(1)某元素的地址
(2)指针变量口头也被称为指针
注意:
对某变量取地址
指针是一个变量,是用来存放地址的变量:指针变量
指针变量的定义:所指向的数据类型* 指针变量名
指针变量的大小:(与指向的数据类型无关)
二 指针类型
2.1指针类型的含义:
2.1.1 不同指针类型决定解引用时候权限不同:
(1)int型(整形)指针解引用可以访问四个字节:
int *p;
*(p+1):跳过4个字节
(2)char型(字符型)指针解引用只可以访问一个字节
char *p;
*(p+1):跳过一个字节
总结:
-
指针的类型决定了对指针解引用时候的权限
-
指针的类型也决定了指针向前或者向后走一步的距离
2.1.2 任何类型的指针变量都能存放地址(即使跨类型)
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = 1;
}
return 0;
}
arr:
p+i:表示下标为i的位置
第一次循环:
p+0,指向不变
第二次:
p+1,指向第一个(跳过一个元素,4个字节)
…
三 野指针(非法的指针):
野指针概念:-----野狗(属于谁不可知)
指针指向的位置位置(随机/不正确的,没有限制的)
3.1 可能出现野指针的情况:
(1) 指针未初始化:指针里面是一个随机值,解引用会造成非法访问内存
这里的p被称为野指针。
局部变量如果不初始化默认为随机值。
int main()
{
int* p;//p是局部指针变量,p里面随机的值被认为是地址
*p = 20;//对随机值进行解引用操作访问空间,找到一块未知的空间(非法访问内存)
return 0;
}
(2) 指针越界:
越界示例:
p的指向:
因为循环进行了11次,i++10次时候,指向的是越界的指针(越界了)
3 指针指向的空间被释放了(已经不属于已有的内存空间)
*p不合法:因为指向的变量a在内存中已经被释放了(销毁了)。
3.2 如何避免野指针:
1 注意指针要初始化
(1)当指针变量p初始化不知道应该指向谁的时候,定义初始化为NULL(空指针)
(2)明确知道指针变量初始化的值,将某变量的地址赋给指针变量就可
2 小心指针越界
3 指针指向空间释放之后,及时将该指针变量置为空指针
4 指针使用前要检查有效性(使用指针变量时,指针变量不能等于空指针)
四 指针运算:
4.1 指针±整数:
*vp++=0:指针变量vp先解引用并且赋值操作后,指针变量再进行更改vp++(指向的位置发生变化),这里的vp++就成为指针变量的加减运算(实质上的指针指向位置的变更)
指针的关系运算(指针变量的高低比较)
p<=pend是指针的关系运算,p++是指针加整数
4.2 指针-指针:
数组中第九个元素的地址减去第0个元素的地址,得到的结果是9(两者之间元素的个数)
为什么指针相减得到的是一个整数?
是两指针之间的元素个数
指针相减的前提:是两个指针指向同一块空间
利用指针相减模拟实现strlen库函数实现对数组元素个数的计数:
那么指针+指针? 没什么意义
五 数组和指针之间的关系
数组名:就是数组首元素的地址(多个字节中的第一个字节的地址)
前后一样(p为首元素的地址,p+i就是下标为i的元素的地址)
六 二级指针:
pa指针变量也是变量,在内存中也有指针变量的地址,&pa也是可行的,取出pa在内存中的起始地址:
在内存空间中:
因此可以有无限级指针(无限套娃)
七 指针数组:存放指针的数组(本质上是数组)
其他:
指针变量的*靠近变量名称,这样同时定义多个时候不会产生歧义。
(本质上编译器都能识别)