目录
前言
编辑
指针
内存与地址
计算机常见单位
理解编址
取地址,指针变量,解引用
取地址
指针变量
解引用
指针变量大小
指针类型的作用
char*解引用后
指针+-整数
应用
void*指针
const修饰指针变量
const修饰普通变量
const修饰指针变量
理清pa与pa*的含义
代码 int const*pa=&a;
编辑 代码 int *const pa=&a;
指针计算
指针-指针
应用:模拟实现strlen函数
野指针
成因
指针未初始化
指针越界访问
指针指向空间释放
规避野指针
前言
你是否也是在学习c语言碰到了拦路虎?
下面,我将通过这篇文章来和大家一起了解并熟悉c语言指针,拿捏指针的每一处细节~
创作不易,可以帮忙点点赞吗
如有差错,欢迎指出
指针
c语言中的指针其实就是计算机内存中的地址,即内存单元的编号。通过地址,CPU就可以快速找到一个内存空间。
所以 内存单元的编号==地址==指针
但是我们口头上的指针实际是指针变量。
内存与地址
计算机中的内存可以类比为生活中的一栋房子,地址则是房子中每个房间的门牌号。
内存被划分为内存单元(1个字节),
计算机常见单位
1byte(字节)=8bit(比特位)
1KB=1024byte
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
理解编址
如图 以下为CPU和内存之间交互数据的大致模式
若CPU要从内存中取出一个值,则cpu通过控制总线下达取出的命令,通过地址总线获得内存中的地址,通过地址找到目标值后,再通过数据总线传给CPU。
若CPU要在内存中存储一个值,则cpu通过控制总线下达存储的命令,通过地址总线给目标值开辟一个空间,并编址,通过地址,CPU通过数据总线把值传给内存,并存储起来。
取地址,指针变量,解引用
取地址
如图,在32位的机械下,打印变量a的地址
其中a占4个字节,打印的地址其实是第一个字节的地址
指针变量
指针变量是专门存放地址的,
如图
int* pa = &a;
pa 是 指针变量 用于存放地址(指针)
*说明pa是指针变量,int说明pa指向的对象是int类型的
解引用
*pa =20 ;
* 解引用操作符,意为通过pa中的地址找到a
*pa等价于a,所以等同于代码a=20
指针变量大小
指针变量大小取决于一个地址的存放需要多大空间
32位机器上:地址线是32根,地址的二进制序列就是32bit位,要4字节(32bit位)的空间存放地址。所以32位机器的指针变量大小都是4个字节。
指针变量大小与类型无关,在相同的平台下,大小都相同。
如图
32位机器
同理,64位机器上,指针变量大小都是8个字节。
64位机器
指针类型的作用
指针类型决定了对指针解引用的时候有多大权限(一次能操作几个字节)
比如 char*的指针解引用就只可以访问1个字节,而int*是4个。
图解如下
未解引用之前
int*解引用后
char*解引用后
指针+-整数
指针的类型决定了指针向前或向后走一步有多大(距离)
如图不同指针类型加减整数的结果
int*的pa+1
char*的pa+1
应用
#include<stdio.h>
//指针+-整数的应用
int main()
{
int arr[10] = { 0 };
int* p = &arr[0];
//将数组全部初始化为1
for (int i = 0; i < 10; i++)
{
*p = 1;
p++;
}
//打印
p = &arr[0];//再让p回到起始位置
for (int i = 0; i < 10; i++)
{
printf("%d ", *p);
p++;
}
return 0;
}
void*指针
void*指针是无具体类型的特殊指针(泛型指针),可以接受任意类型地址
但是 不能直接进行解引用操作,也不能进行指针+-整数
const修饰指针变量
const修饰普通变量
如图,const仅仅是在语法上做了限制,我们习惯叫a为常变量
用指针变量pa间接修改a的值却不会报错,无视const。
const修饰指针变量
const修饰指针变量
理清pa与pa*的含义
pa里面存放的是地址(a的地址)
pa是变量,有自己的地址
*pa是pa指向的空间
代码 int const*pa=&a;
const限制的是*pa,修改*pa会报错,但修改pa的值没问题
代码 int *const pa=&a;
const限制的是pa,可以修改*pa,但修改pa会报错
指针计算
指针-指针
指针-指针 即 地址-地址,得到的绝对值是指针和指针之间的元素个数
前提条件:两个指针指向同一块空间
应用:模拟实现strlen函数
分别使用了 指针-整数 和 指针-指针两种方法
其中代码while(*s!='\0')可以简化为while(*s)
因为\0的ASCII码值为0,地址加到\0时(0为假)自然会跳出循环
//指针-整数
int my_strlen1(char* s)//传字符串的地址,返回字符串长度
{
int count = 0;
while (*s != '\0')
{
count++;
s++;//地址+1
}
return count;
}
//指针-指针
int my_strlen2(char* s)
{
char* start = s;
while (*s != '\0')
{
s++;
}
return s - start;//地址-地址
}
#include<stdio.h>
int main()
{
//strlen 求字符串的长度 求‘\0’之前的字符串长度
int len =my_strlen1("abcda");//模拟实现strlen函数
printf("%d\n", len);
len = my_strlen2("abcda");//模拟实现strlen函数
printf("%d\n", len);
return 0;
}
结果
野指针
野指针是指针指向位置是不可知的(随机的、不正确的、没有限制的)
成因
指针未初始化
指针越界访问
指针指向空间释放
规避野指针
初始化指针;若不知道指针应该指向哪里,可以指向NULL
所以,指针变量不使用时,要及时置NULL
NULL是c语言中的标识符常量,值为0,地址也为0,但此地址无法使用,读写地址会报错