一. 指针
利用指针,可以找到相对应内存地址(唯一的一段编号),从而定位数据.
(通俗来说,指针就是变量,用来存放内存单元的地址)
保存一段 16进制的 地址编号
二、指针类型/变量:
- 类型: 基础类型+* 如: int* char*
- 指针变量: int* pa pa就为指针变量.
- 解引用符号: * 放在变量前面 表示这一个变量数据 , 简单的 指针变量仅仅表示一段地址.
- 取地址符号: & 取出所对应的内存单元的地址
一般存储地址方法:
int a = 123;
int* pa=&a; //将a的地址 赋值 给指针变量pa
*pa = 20; //将pa解引用 重新赋值
1. 一个内存单元多大?
一字节
2. 一个指针变量大小:
32位平台 为 4字节 , 64位平台 为8字节
3. 为什么指针变量一样大,为什么不同的指针类型呢?(指针类型意义)
2个16进制位= 8个2进制位= 1字节
意义1 : (指针类型决定了指针进行解引用操作时,能访问的空间大小)
比如:
当同时分别往2个不同类型的 指针变量存入 一个 0x11223344,然后再解引用.
解引用修改变量数据时, int *是修改4字节, 但是char*修改1字节, double* 修改8字节
(所以当赋值时,应该赋值合适的指针类型)
#include<stdio.h>
main()
{
int a = 0x11223344;
int* pa=&a; //将a 的地址取出,放入 pa指针中
char* pc=&a;
printf("%p\n", *pa); //取出指针变量 pa中的值
printf("%p", *pc);
}
输出结果:
0000000011223344
0000000000000044
意义2 : 指针类型决定了:指针一步走多远(指针的步长)
#include<stdio.h>
main()
{
int a = 0x11223344;
int* pa=&a; //将a 的地址取出,放入 pa指针中
char* pc=&a;
printf("%p\n", *pa); //取出指针变量 pa中的值
printf("%p", *pc);
}
计算结果:
000000B515CFF898
000000B515CFF895
计算 地址+1:
- *p= 11223344; (16进制)
- int*p+1 是在原先地址上+4 :127
- char*p+1 是在原先地址上+1 :124
- double*p+1 是在原先地址上+8 :12b
三、野指针:
1.含义:
指针指向的位置是不可知的(可能是随机的,不正确的,不明确的)
2. 造成野指针的原因:
1).指针未初始化(局部变量不置初值,默认是随机值)
2).指针越界
比如 一个数组大小为12,但是循环时指到了地址 13, 就会报错.
3).指针指向空间释放
当指针垮函数使用时, 由于子函数可能创建的是一个 临时变量,当子函数返回指针时,临 时变量也将取消,当主函数再次使用值时,发现是一个释放掉的空区域.
3.避免野指针:
1).指针未初始化
2).指针越界
3).指针合适赋值为 nill, 空指针无法被访问
4).使用前检查有效性
四、指针运算
1.指针+-整数
p+1 表示 地址位置根据 数据类型 往后面移位置
*p+1 表示 p中存储的数据+1
#include<stdio.h>
main()
{
int arr[] = { 1,2,3,4,5 };
int i;
int* p = arr; //将数组首地址赋值 指针变量p
for (i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ",*p); //输出 指针变量 p中的值
p++; //p 的位置 一字节一字节的 往后移. 1 到 2 到 3.....
}
}
输出结果:
1 2 3 4 5
sizeof(arr) / sizeof(arr[0]) // 表示数组长度
2.指针-指针
指针-指针, 表示 两指针中间的元素个数.(必须保证是同一空间,同一类型)
#include<stdio.h>
main()
{
int arr[] = { 1,2,3,4,5 };
int i;
int* p1 = &arr; //将数组首地址赋值 指针变量p
int* p2 = &arr[2];
printf("%d ", p2-p1);
}
结果为 2
3.指针关系运算
注: 标准规定,允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针作比较,但不允许和第一个元素之前的内存位置的指针作比较
允许p2 和p3
不允许p2 和p1
虽然在绝大部分情况下可以运行成功
#include<stdio.h>
main()
{
int arr[5] = { 1,2,3,4,5 };
int i;
int *p2;
for (p2=&arr[5]; p2>&arr[0];) //将最末端小于或等于最前段时 ,停止
{
*--p2 = 0; //赋值为0
printf("%d ", *p2);
}
}
结果:0 0 0 0 0
五、指针与数组
1.首地址代表 :
数组名
&数组名[0]
2.不代表首地址情况:
&数组名 表示整个数组,取出整个数组地址
sizeof(数组名) 表示整个数组,计算整个数组的大小
六、二级指针
int main()
{
int a=10;
int* aa=&a; //一级指针 类型 int* ,存的变量的地址
int** aaa=&aa; //二级指针 类型 int** ,存的指针的地址
**aaa=20; //修改了a的值为20
}
七、指针数组/数组指针
指针数组:存放指针的数组
数组指针:指针
int main()
{
int a=1;
int b=2;
int c=3;
int* arr[3]={&a,&b,&c}; //存储3个地址,称为指针数组
int i=0;
for(i=0;i<3;i++)
{
printf("%d",*(arr[i])); //循环打印出 abc中的值
}
}