static关键字,在我们平常写代码的时候经常用到,特别是在做一些嵌入式编程时时常用到。
static关键字修饰的对象:1、变量,2、函数
static关键字的作用:
- 1、在函数体修饰变量时,一个被声明为的static静态变量在这一函数被调用过程中维持其值不变。在下一次调用时,这个值还是维持上次调用结束时的值。
- 2、在模块内(但在函数体外)修饰变量时,一个被声明为的static静态变量可以被模块内所用函数访问,但不能被模块外其它函数访问。准确地说static关键字在模块内的作用域是从定义之处开始,到文件结尾处结束。它是一个本地的全局变量,当然在函数调用过程中这个变量的值也会维持不变。
- 3、在模块内修饰函数时,一个被声明为静态的函数只可被这一模块内的其它函数调用。 那就是 ,这个函数被限制在声明它的模块的本地范围内使用。这样做的好处一是能避免不同模块之间函数重名时发生冲突;另外static关键字也告诉了编程人员这个函数只能在本模块里面使用,不能被外部模块调用,避免了代码维护时意外调用。
名词解释:
函数体:我们写的函数int main{……};void fun{……};花括号里面的内容就是函数体。
模块:一般我们建立一个工程的时候,都会有几个模块,比如主函数main.c,LED程序led.c,蜂鸣器函数beep.c;每一个.c文件都可以称为一个模块。
static变量的储存位置:
static关键字当然就是放在静态储存区了。
静态存储可分为.bss/.data/.rodata等数据段(section)。
拓展:
储存区可分为三类:
- 1、静态存储(static storage);静态存储可分为.bss/.data/.rodata等数据段(section)
- 2、自动存储(automatic storage);自动存储则对应的是栈(stack)
- 3、动态分配存储(allocated or dynamic storage);动态分配存储对应的是堆(heap)
以STM32为例:
STM32的内存结构:STM32的Flash、SRAM、寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。可访问的存储器空间被分成8个主要块,每个块为512MB。
而我们开发者主要在下面两个区域要考虑内存的分配。
- FLASH用于存储下载的程序。(掉电数据不消失)
- SRAM是存储运行程序中的数据。(掉电后数据消失)
所以只要不外扩存储器,写完的程序中的所有东西也就会出现在这两个存储器中。当然我们
STM32的SRAM内存分配也可以分为这3大类。
STM32的静态储存区:(也有3个数据段)
(代码中的全局变量,静态变量存放地方)
- bss段: bss段(bss segment)通常是指用来存放程序中未初始化的全局变量或静态变量的一块内存区域 。
- data段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量或静态变量的一块内存区域。
- rodata段:用于存储const变量和指令。
静态数据区,所保存的变量在使用过程中不会被销毁;所以全局变量、静态变量都会维持上一次赋值的值。而const可以理解为只读变量,意思就是你只要读取它的值就好了,用const修饰就是希望你不要去修改它;所以这个值在使用过程中是保持不变的。
STM32的自动存储区:
栈(stack):
栈也就是堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数花括号“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。
这些变量在代码运行结束后数据销毁。由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。
STM32的动态分配存储区:
堆(heap):
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
在玩STM32时我们主动操作堆一般是在操作系统上(比如:Free RTOS),平常编写裸机代码用到的机会不多。
另外: STM32还有一个 text段(放代码的区域):代码段在FLASH里储存
代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。