C语言指针难吗?纸老虎而已,纯干货讲解( 三 )


 

C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
变量和内存
为了简单起见,这里就用上面例子中的 int num = 97 这个局部变量来分析变量在内存中的存储模型 。
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
已知:num的类型是int,占用了4个字节的内存空间,其值是97,地址是0028FF40 。我们从以下几个方面去分析 。
1、内存的数据
内存的数据就是变量的值对应的二进制,一切都是二进制 。
97的二进制是 : 00000000 00000000 00000000 0110000 , 但使用的小端模式存储时,低位数据存放在低地址,所以图中画的时候是倒过来的 。
2、内存数据的类型
内存的数据类型决定了这个数据占用的字节数,以及计算机将如何解释这些字节 。
num的类型是int,因此将被解释为 一个整数 。
3、内存数据的名称
内存的名称就是变量名 。实质上,内存数据都是以地址来标识的,根本没有内存的名称这个说法,这只是高级语言提供的抽象机制,方便我们操作内存数据 。
而且在C语言中,并不是所有的内存数据都有名称,例如使用malloc申请的堆内存就没有 。
4、内存数据的地址
如果一个类型占用的字节数大于1,则其变量的地址就是地址值最小的那个字节的地址 。
因此num的地址是 0028FF40 。内存的地址用于标识这个内存块 。
5、内存数据的生命周期
num是main函数中的局部变量,因此当main函数被启动时,它被分配于栈内存上,当main执行结束时,消亡 。
如果一个数据一直占用着他的内存,那么我们就说他是“活着的”,如果他占用的内存被回收了,则这个数据就“消亡了” 。
C语言中的程序数据会按照他们定义的位置,数据的种类,修饰的关键字等因素,决定他们的生命周期特性 。
实质上我们程序使用的内存会被逻辑上划分为:栈区,堆区,静态数据区,方法区 。
不同的区域的数据有不同的生命周期 。
无论以后计算机硬件如何发展,内存容量都是有限的,因此清楚理解程序中每一个程序数据的生命周期是非常重要的 。
指针运算
N多的面试会考这种东西了:
??????Type *p; p++;然后问你p的值变化了多少 。
其实,也可以认为这是在考编译器的基本知识 。因此p的值并不像表面看到的+1那么简单,编译器实际上对p进行的是加sizeof(Type)的操作 。
看一个一段代码的测试结果:
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
这里注释掉char一行的原因是因为cout<<(char*)会被当成字符串输出,而不是char的地址)
执行结果:
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
观察结果,可以看出,他们的增长结果分别是:
2(sizeof(short)) 4(sizeof(int)) 4(sizeof(long)) 8(sizeof(long long)) 4(sizeof(float)) 8(sizeof(double)) 12(sizeof(long double))
喏,增加的值是不是sizeof(Type)呢?别的什么struct,class之类的,就不验证你,有兴趣的自己去验证 。
我们再对这样的一段代码进行汇编,查看编译器是如何进行指针的加法操作的:
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
汇编结果:
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 

C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
注意看注释部分的结果,我们看到,piv的值显示加了4(sizeof(int)),然后又加了16(4*sizeof(int)) 。
指针变量和指向关系
用来保存指针的变量,就是指针变量 。
如果指针变量p1保存了变量 num的地址,则就说:p1指向了变量num,也可以说p1指向了num所在的内存块,这种指向关系,在图中一般用 箭头表示 。
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
上图中,指针变量p1指向了num所在的内存块,即从地址0028FF40开始的4个byte 的内存块 。
定义指针变量
C语言中,定义变量时,在变量名前写一个 * 星号,这个变量就变成了对应变量类型的指针变量 。必要时要加( ) 来避免优先级的问题 。
引申:C语言中,定义变量时,在定义的最前面写上typedef,那么这个变量名就成了一种类型,即这个类型的同义词 。


推荐阅读