1.地址和内存
1.1内存
内存对应的就是计算机中16GB/32GB等内存空间。其中把内存划分为一个一个单元,每个内存单元取一个字节。1个比特位可以存储一个二进制的1或者0。
常见的单位如:
bit--比特位 1byte=8bit
byte--字节 1KB=1024byte
MB 1MB=1024KB
GB 1GB=1024MB
TB 1TB=1024GB
PB 1PB=1024TB
每个内存都会有一个编号 这就是地址,CPU可以通过这个编号快速找到一个内存空间。我们将其取名为指针。
也就是说内存单元编号=地址=指针
1.2如何取出地址
当我们需要使用这个地址时,用&操作符,例如这是个int类型,那么&会得到第一个字节的地址。
1.3指针变量
当我们取出地址后,为了方便后期使用会将其储存起来,这时候就应用到指针变量,指针变量可以将其储存。
此时p的类型就为int*,*说明p是指针变量,int说明他是整型对象。a中存储的是10这个数字,p中存储的是a的地址,通过这个地址我们可以顺藤摸瓜找到a。同理其他类型指针也是如此。
1.4解引用操作符
我们将地址存储起来,未来是要使用的,那么怎么使用呢?
如图我们应用到了一个(*)操作符,p是存放a的地址,通过*将p解开,得到了里面的内容。相当于说p是存放东西的盒子,*是打开盒子得到盒子里面的东西。
1.5指针变量的大小
在x86和x64的环境中指针变量的大小不同。首先,在x86中是由32位机器32根地址总线,那么一个地址就是32bit。同理在x64环境中,则有64根地址总线,一个地址存储起来就需要8个字节也就是64个bit。
所以指针变量的大小和类型无关,只要是指针变量在相同平台下,大小都是相同的。
那么指针变量不同类型的意义在哪呢?
通过运行这两个代码我们发现,第一个代码只改变了第一个字节,而第二个代码则改变了4个字节。
所以我们得出结论:指针的类型决定了,对指针解引用访问的时候有多大权限(一次能操作几个字节)。
2.Const修饰指针
2.1const修饰变量
constant可以给变量上增加一些限制,使其不能被修改。
2.2const修饰指针
const修饰指针放在*左边和右边是不同的。
当const放在*左边时,修饰的是指针指向的内容,保证指针指向的内容不被修改,但指针变量本身可修改
当const放在*右边时,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容可以改变。
3.指针运算
3.1指针+-整数
数组在内存中是连续存放的,只要知道第一个地址的元素,顺藤摸瓜可以知道后面所有元素。
3.2指针-指针
3.3指针运算关系
4.指针的使用和传址调用
4.1strlen的模拟实现
库函数strlen的功能是求字符串长度,统计的是字符串中\0之前的字符个数,最终返回长度。模拟实现只要从起始地址开始向后逐个字符遍历,只要不是\0,计数器就+1,遇到\0就停止。
4.2传值调用和传址调用
通过调试上面的代码我们发现形参接受了a和b的地址,但是同时也创建了x和y的地址,x和y相当于是独立的空间,那么在函数中交换x和y就不会影响到a和b。
结论:实参传给形参时,形参会单独创建一份临时空间来接受形参,对形参的修改不影响实参。
那应该怎么办呢?
我们可以将a和b地址传给形参,这样通过地址可以对a和b直接进行值的交换。
这样我们就传址成功了,传址调用可以让函数与主调函数之间建立真正的联系,在函数内部实现修改。