江浙沪做网站的公司在线seo短视频
1. 内存和地址
2. 指针变量和地址
3. 指针变量类型的意义
4. const修饰指针
5. 指针运算
6. 野指针
7. assert断⾔
8. 指针的使⽤和传址调⽤
1. 内存和地址
1.1 内存
计算机内存空间如何高效率的管理?
也是把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节
⼀个⽐特位可以存储⼀个2进制的位1或者0
1byte(字节) = 8bit(比特位)
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
内存单元的编号==地址==指针
1.2 究竟该如何理解编址
CPU访问内存中的某个字节空间,必须知道这个 字节空间在内存的什么位置,⽽因为内存中字节 很多,所以需要给内存进⾏编址
2. 指针变量和地址
2.1 取地址操作符(&)
如果想要获得a的地址就要输入&a
2.2 指针变量和解引⽤操作符(*)
那我们通过取地址操作符(&)拿到的地址是⼀个数值,如果需要存的话,要将这个数放在,指针变量中
指针变量也是⼀种变量,这种变量就是⽤来存放地址的,存放在指针变量中的值都会理解为地址
2.2.2 如何拆解指针类型
比如
int a = 10;
int * pa = &a;
这⾥pa左边写的是 int*类型的对象。 * 是在说明pa是指针变量,⽽前⾯的 int 是在说明pa指向的是整型(int)
2.2.3 解引⽤操作符
当我们需要用到这个指针变量时可以用解引⽤操作符(*)
如:
*pa 的意思就是通过pa中存放的地址,找到指向的空间, *pa其实就是a变量了;所以*pa=0,这个操作符是把a改成了0
2.3 指针变量的⼤⼩
32位平台下地址是32个bit位,指针变量⼤⼩是4个字节
64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
注意 :指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的
3. 指针变量类型的意义
3.1 指针的解引⽤
对比两个代码发现:int*类型会将n的4个字节全部改为0,但是char*类型只是将n的第⼀个字节改为0
指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)
3.2 指针+-整数
char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节
3.3 void* 指针
这一段代码执行后会报出一个警告
使用void*
⼀般 v oid* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址
4. const修饰指针
4.1 const修饰变量
这里可以发现const加上后 n的值不能被修改
但是可以通过修改n的地址去修改它的值
如:
4.2 const修饰指针变量
5. 指针运算
指针的基本运算有三种分别是:
1. 指针+-整数
2.指针-指针
3.指针的关系运算
5.1 指针+-整数
5.2 指针-指针
5.3 指针的关系运算
6. 野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
6.1 野指针成因
1. 指针未初始化
2. 指针越界访问
3. 指针指向的空间释放
6.2 如何规避野指针
1. 指针初始化
2.⼩⼼指针越界
3.指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性
4.避免返回局部变量的地址
7. assert断⾔
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报 错终⽌运⾏。这个宏常常被称为“断⾔”
如
如果p不等于0程序继续运⾏,否则就会终⽌运⾏,并且给出报错信息提⽰
如果需要使用assert则需要加上#include<assert.h>
如果已经确认程序没有问 题,不需要再做断⾔,就在 #include<assert.h> 语句的前⾯,定义⼀个宏 NDEBUG
8. 指针的使用和传址调用
8.1 strlen的模拟实现
库函数strlen的功能是求字符串⻓度,统计的是字符串中
8.2 传值调用和传址调用
举例:写⼀个函数,交换两个整型变量的值
按照之前思维编写后,发现有误。
在Add(int x,int y )的时候
a和b的值都给了x,y
且x和y也交换了。在Add函数内部交换x和y的值,不会影响a和b。,当Add函数调⽤结束后回到main函数,a和b的没法交换。Add函数在使⽤ 的时候,是把变量本⾝直接传递给了函数,这种调⽤函数的⽅式我们之前在函数的时候就知道了,这 种叫 传值调用。
结论 实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实 参。
修改代码
我们可以看到实现成Swap2的⽅式,顺利完成了任务,这⾥调⽤Swap2函数的时候是将变量的地址传 递给了函数,这种函数调⽤⽅式叫:传址调用
传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所 以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改 主调函数中的变量的值,就需要传址调⽤