|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
C语言程序的动态内存分为栈内存区域和堆内存区域两种。栈内存是由编译器管理的,而堆内存是由程序调用具体的库函数管理的。我们今天分析下栈内存的概念。4 o; m( t$ m; J f0 l2 j+ f
0 ?& }! W- W5 A1 q" Z$ X) L5 x7 r- f$ J8 I8 [0 Y+ b8 x2 [' q+ A
栈内存的使用在很大程度上依赖于处理器的硬件机制。在处理器中,一般有一个寄存器来表示当前栈指针的位置,通常在内存中分配一块区域,这块内存的上界(高内存地址)和下界(低内存地址)之间是可用的栈内存区域。; m0 f: ?' c- P. m! y8 ]) E4 @% I
! j, R: u/ n9 Y/ U0 S
栈指针是一个指向栈区域内部的指针,也就是它的值是一个地址,这个地址位于栈区的下界和栈区的上界之间。栈指针把这个栈区域分为两个部分,一个是已经使用的区域,一个是没有使用的区域。
% F* |& o0 D) ]3 y: z) y
0 d( `( h; `" _- H* Y$ h& |对于栈内存的增长方向有两种:一种是向上增长的,也就是低地址向高地址增长;另一个是向下增长的,高地址向低地址增长。在目前常见的体系结构和编译系统中,栈大多是向下增长的,我们也是看下这种常见的增长形式。在初始阶段,栈指针是指向栈区间的上界。随着栈使用量的增加,栈指针的值将向低地址移动,也就是在变小。
4 u; R4 W1 Z2 {/ N4 s8 |* C: m5 m9 k1 J) H
栈内存在使用过程中有一个重要的特性是先入后出,也就是后入栈的内容将先出栈,而先入栈的后出栈。类似于一个口的瓶子,先进去的在底下,要想底下的出来就先把上面的先倒出来。栈内存的使用情况见下图:8 B) {% i7 Y* G& X% K& s) N) h2 b
1 j/ B% @. F d! `
入栈的过程和出栈的过程我们安全用图形来表示,更形象些吧~6 @7 w! ~ N) n" ], i8 ]
" S( I. g0 M- x3 y9 c$ W
, {+ A* w# t, i% _( `" |& {, ]) t r在入栈的过程中,如果栈指针的变化超出栈内存的区域,将发生栈溢出。, Q Z( D/ ~8 e# S& ~- K1 L4 J2 a. _
) I3 |. w; o- _! d. q' v
从图中看出栈指针的功能是标识当前的栈位置。对栈内存处理中,每次能够获取的内容都是最后可放入栈内存的内容,而每次放入栈内存中的内容都将位于栈区域的最后。
" B5 H# W5 i7 S" O- E' t. c! R* ^1 G
o" s) @7 P! _3 H总的来说其实栈是一个先入后出的内存区域,栈指针是提供一种硬件的内存机制。
% _3 _0 e: ]$ m0 G8 y1 S0 K* O% s( g3 m
还有一个大家可能都没听说过,或者都没关注过的,我们来一起了解一下,就是满栈和空栈的概念,我们还是通过图来形容一下,这个是由处理器的体系结构决定的。与程序的编写没有关系,甚至编译器都不需要关注这个问题。无论在哪种情况下,栈指针都是已经使用的栈区域和未使用的栈区域的分界线。
- u) J3 }6 W0 Z$ W1 S! {4 p/ _% J. f
2 L4 E+ p/ y( [6 V6 o6 i% S在满栈的情况:栈指针当前的位置是已经使用的栈区域。% Q4 P2 m9 X! N* f* |5 {1 ]
9 t5 e9 U, E+ E" H6 G在空栈的情况:栈指针当期的位置是没有使用的栈区域。- S7 l3 f: m8 O* E7 K* B( I
7 a6 p6 j* V: W( X. H/ N! l这个仅供大家了解下就可以了,毕竟对于我们大多数人来说都是应用者,多了解点底层的总没错,但也不必太深挖。对于栈内存的概念我就分享到这里,其实这个对于写汇编的人来说就很有用处了,或者去多读一些汇编就很能清楚栈内存的妙用了。后续我分享堆内存的一些概念,话说知识是一点点积累的过程,有时候觉得前面有的知识点懵懵懂懂的突然连起来就又通透了。这就是坚持学习的作用,希望大家都能坚持多学,才能更会用。
2 W5 M+ s% C$ k" I2 g9 z0 e% C/ s0 E: A: b% r7 e, ]
* ~3 @: [$ x; }1 k, C
( ] h" w# G) W( W
* D7 W E3 j* E) x, `% o( Q% x |
|