从内存和内存的分区的角度来理解数据类型 、变量、指针。

一、什么事数据类型?

      数据类型可以理解为是 代表一定大小的内存块的别名。

     例如:整型 int ,他代表的是固定大小为4个byte的内存块;short 是固定1 byte 的内存块。

    当我们使用内存的时候,就会去内存空间去申请相应大小的内存块。

  例如:int num = 1;  我们理解为在内存空间里申请了4 byte 大小的内存块 来存放数值 1.(那num 又如何理解呢?继续看下面的分析)

二、 什么是变量?

     曾经我经常会把变量当作是一块内存,其实不然。变量的理解应该是 :

     1、概念:既能读又能写的内存对象。若一但初始化就不能修改的内存对象称之为常量。

     2、定义形式: 数据类型 标识符;

     变量的本质:

      前面说了int num = 1;是在4 byte的内存块中存放了数值1,那么num是代表这个内存块吗?我把num理解为是这块内存的标号,是这个内存块的首地址,在他之后的4 byte内存区域都是我们申请的内存区域。当我们对num 取地址操作的时候(&num)就会得到这块内存的起始地址。

   1、程序通过变量来申请和命名可用内存空间 ,并且给予数据类型。int num = 1;

   2、通过变量来访问一段内存空间,这段空间的名字(门牌)是num,大小长度是数据类型(int)决定的。

   3、修改变量的方法:

           (1) 直接:  num = 10;

            (2) 间接:  首先我们可获得要操作的内存块的地址  # 然后通过地址进行对内存空间的内容做修改。

    4、变量的四要素:名称、大小、作用域、生命周期。


*******上面所说的操作不是对变量进行读写操作,实质都是对内存空间进行操作,那么变量num跑哪去了呢?继续思考。。。内存的分区分析。


  三、内存的分区:

        大概可以把内存分为几个区:代码区,全局区(静态区)(static),常量区,堆区,栈区。(当然这里没有进行更细致的分析)

        代码区:存放程序的二进制代码。(不进行研究考虑)

        全局区(静态区)(static):有操作系统进行管理,该区域在程序结束后有操作系统进行释放回收。(其中对全局变量和静态变量初始化的在一个区,没有初始化的在另一个区bass段)。申请的全局变量或者静态变量,他们的生命周期是整个程序,所以说,无论在什么时候,只要是程序没有结束就可以访问。在任何时候对其修改都会对以后其它语句使用产生影响。其中如果是static修饰的局部变量,虽然它的生命周期是整个程序,但是它的作用域是申请它的那部分语句。

        常量区:程序结束后有操作系统进行释放和回收。存放字符常量和其他常量的地址。对于常量区应该注意,如果一个程序中有很多的函数,并且他们都申请了常量区的内存,并且他们的常量值相同,那么在编译器编译优化时候会对其进行优化,使各个函数使用相同的地址(常量值的地址)。

        堆区(heap):一般由程序员进行分配和释放,如果程序员没有释放,那么程序结束时可能(是可能)被操作系统进行释放回收。堆区的利用多是由程序员自己申请,想用多少就申请多少(在linux下以内存页的方式申请利用)。切记按习惯当使用完堆区申请的内存空间后要手动释放掉。这样不仅不会浪费计算机的内存,而且不容易出现意想不到的错误,还更利于逻辑分析。

        栈区(stack):有编译器自动分配和释放。存放函数的参数值,局部变量的值等。栈的结构想必都清楚,简单一句话:先进后出,后进先出。在这里要注意的是,在很多个调用函数被调用时,先调用的函数的参数和变量先入栈,而后被调用的函数后入栈,也就是形成了函数的调用嵌套,而后调用的函数要先结束,先调用的函数后结束,依旧是因为栈区的内的函数的参数和变量的先后顺序决定的。所以说函数的调用的关系与内存的分区中栈区的性质有直接关系。

    *****充分理解了各个分区对内存的申请和释放回收方式才能更好的理解的指针与变量之间的关系。

  四、关于指针:

     经典语句:指针指向谁就把谁的地址赋给指针。

    指针是一种数据类型,大小为4 byte,用来存储地址数据。

    格式: 数据类型 *  标识符; 例如 char * p;意思是:指向字符地址(或者字符串的首地址)的字符指针类型 的变量p(代表带下为4byte的内存块),既然p代表内存块,那么p也是代表一个地址 ,也可以用一个指针类型的变量来存储记录,这就是二级指针**pl。当然还有三级指针等等。

    指针经常用在被调用函数和调用函数之间的数据输入与输出(就是数据的交换)。如果用数组做函数是形参,会浪费内存,这是我们就可以用指针做函数的形式参数,来接收调用函数传来的实参地址,这样我们就可以大量的利用调用函数的数据了。同样,我们可以将被调用函数的内数据的地址赋值给指针,再将指针作为返回值返回给调用函数,这样调用函数就可以使用被调函数的大量数据。但要注意,对于函数返回值要及时用调用函数的变量保存起来,或者直接利用。因为被调用函数内申请的变量(无特殊情况)都是在栈区申请的,当被调用函数结束后就会被释放,导致数据丢失没有及时被利用的后果。


*******没有内存就没有首地址,没有首地址就没有指针。


*****不论是数据类型、或者变量 ,或是指针,从内存的分区来理解会更深刻。


以上只是我个人的理解,对于c语言和其它高级语言(如java)来比较,C语言更重于理解的过程,所以学习c语言一顶要在理解的基础上去应用,区搞项目。小弟我才疏学浅,写这些主要还是帮助自己深刻理解C,如果能帮到需要的人更是不胜荣幸。当然有说的不对之处还请大侠指教,不胜感激。


————————后期还会有这个方面的理解补充。-------————让坚持成为一种习惯,让懒惰成为一种奢侈。





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值