C语言内存分布思想概述
内存分布思想概述
通过我们前面对C的学习,我们知道了C就是不断地操作和分配内存类型资源的一种语言,它的核心思想就是如何操作内存。不管是指针还是数组,都是围绕着内存。随着对内存属性的深入,自然而然对于我们理解C的一些编程技巧和更高深的思想是很有帮助的。
内存的属性
大小
不管我们是什么数据类型,在编译器看到这个类型之后,就有一个内存大小为我们服务。只是对于指针而言,还多了一个指向类型的读取方法。
在哪里
在我们编写好代码之后,首先经过编译,再汇编,最后再经过链接。链接过程就是将数据和代码块放到段中。当我们定义一个int a的时候,我们只是指定了它的大小,我们却并没有让编译器知道我们需要将它保存在哪里。这个时候编译器就会采用默认方式将变量存储在一个段中,这个段是内存中存储不同属性数据的分段,所有的分段就构成了内存分布图。学习内存分布图的目的就是明白哪些数据和程序应该放在哪个段上。
测试代码如下
定义了一个变量a,我们通过%p来查看a存储的地址和main函数的地址,%p会在十六进制%x的基础上加上0x,只是为了便于查看。
运行结果如下
通过地址来看,局部变量a存储在高地址段,而main函数存储在低地址段。因为地址段从0x00000000到0xffffffff来说,main函数的地址相对来说是较低的。
我们将变量a定义到main函数的外面,使它成为一个全局变量,然后再运行:此时的内存地址非常相近了。
下图就是内存分布的图,最下面是低地址段。代码段在最低的地址段,再上面就是只读数据段,类似于我们前面定义的双引号字符串常量“Hello world”;再上面就是我们定义的全局变量,刚才我们定义在main函数外面的a就保存在这里。再上面是运行时的堆空间,通过malloc分配的变量保存在这里。再往上就是栈空间,存储局部变量。最上面就是操作系统的核心空间-内核空间,应用程序是不可以访问的,读取都是不可以的,在这个空间之下的被称为0到3G的空间。实际上在代码段往下也有一段内核空间,也是不建议访问的。那我们可以访问的空间就是去掉两头的空间。
对于内存分布图的理解,我们就了解了指针为什么不可以随意的访问一些空间,明白了内存分布图,我们就可以规避一些指针出错的问题,避免段错误的出现。当我们创建一个变量,我们就可以想象它在内存中的分布位置,它的地址是否可以赋值给一个可读的或者是可写的指针变量。