我是靠谱客的博主 高高龙猫,最近开发中收集的这篇文章主要介绍c语言从0开始_8 变量 进程映像 类型限定符进程映像变量类型限定符,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

c语言从0开始_8 变量 进程映像 类型限定符

  • 进程映像
    • text 代码段
    • data 数据段
    • bss 静态数据段
    • heap 堆
    • stack 栈
  • 变量
    • 全局变量
    • 静态全局变量
    • 局部变量
    • 静态局部变量
    • 块变量
    • 注意
  • 类型限定符
    • auto
    • const
    • extern
    • static
    • register
    • volatile
    • typedef

进程映像

程序:储存在磁盘中的可执行的文件(二进制文件、脚本文件)
进程:在系统中运行的程序
进程映像:进程的内存的分布情况

text 代码段

存储的是二进制的指令、常量数据,权限是只读的,如果强行修改会产生段错误

data 数据段

存储的是初始化过的全局变量、被初始化过的静态局部变量

bss 静态数据段

存储的是未初始化过的全局变量、未初始化过的静态局部变量,该内存段在程序执行前会被初始化为0。

heap 堆

由于程序员手动管理,该内存无法与标识符建立映射关系(无法取名字),必须与指针配合使用。
优点:够大,分配和释放可控。
缺点:使用麻烦,容易产生内存泄漏、内存碎片。

stack 栈

由系统自动管理,随着函数被调用,会自动分配内存,函数执行结束后自动释放内存。
优点:使用方便,采用栈结构方式管理安全,不会产生内存泄漏、内存碎片。
缺点:大小有限,一次使用过多可能会产生段错误,分配和释放不可控不适合

变量

变量的属性:存储位置 生命周期 作用域

全局变量

定义在函数外的变量
存储位置: data(初始化过的)或者bss(未初始化过的)
生命周期: main函数运行开始前到程序结束才释放,即整个程序的运行时期
作用范围: 程序中的任何位置,其它源文件中需要声明

静态全局变量

存储位置:data 初始化过的,bss 未初始化的
生命周期:整个程序的运行时期
作用范围:在目标文件内可以使用

局部变量

定义在函数内的
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在本函数内使用

静态局部变量

存储位置:data 初始化过的,bss 未初始化的
生命周期:整个程序的运行时期
作用范围:函数内

块变量

定义在ifforwhile等语句块内的变量
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在语句块内使用

注意

局部变量和全局变量可以同名,但是会屏蔽同名的全局变量,同名块变量会屏蔽同名的局部变量和全局变量
        建议:全局变量首字母大写 

类型限定符

auto

用于定义自动申请、自动释放的变量(局部变量),不加代表了加。早期用于定义临时变量(局部变量和块),C11标准中它可以用于定义自动推导类型的变量。现在看来没什么用。只有在使用时才为该类型变量分配内存。
不能用于修饰全局变量

const

显示地"保护"变量不被修改
但是,如果要强制修改还是可以修改的
如果对初始化过的全局变量,用const修饰后,存储位置从data变成了text

extern

声明外部的全局变量,声明的变量已在别处定义过,请放心使用
但是只能临时通过编译,如果没有定义,链接时依然会报错
只是声明变量,不能赋值

static

被static修饰过的变量称为静态局部变量,局部全局变量
改变存储位置:
改变局部变量的存储位置,由stack改data或者bss(由是否初始化决定)
延长生命周期:
延长局部变量的生命周期
限制作用范围:
限制全局变量、函数只能在本文件内使用
可以防止函数、全局变量重名、防止被别人调用

register

存储介质:
硬盘->内存->高速缓存->寄存器->CPU

申请把变量的存储介质由内存转移到寄存器存储,如果能成功,数据的读取速度会大幅提升,寄存器数量有限,申请可能失败

好处:
register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
register修饰符有几点限制;
1.register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。
2.因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。
3.只有局部自动变量和形式参数可以作为寄存器变量,其它(如全局变量)不行。
4.局部静态变量不能定义为寄存器变量。不能写成:register static int a, b, c;
5.由于寄存器的数量有限(不同的cpu寄存器数目不一),不能定义任意多个寄存器变量,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。

volatile

编译器的取值优化:
变量的值没有发生改变时,后续的取值会进行优化,不再去内存中读取,而是使用第一次读取的结果,可以节约时间
使用volatile修饰的变量不做取值优化
volatile int num = 10;
if(num == num)
{
//可能为假
}
一般硬件编程和驱动编程时使用

typedef

类型重定义,注意不是替换关系,定义变量时如果前面加上typedef,则变量名就变成了类型
typedef int num;
#define num int;
num num2;
uint8_t size_t time_t
typedef unsigned char uint8_t

最后

以上就是高高龙猫为你收集整理的c语言从0开始_8 变量 进程映像 类型限定符进程映像变量类型限定符的全部内容,希望文章能够帮你解决c语言从0开始_8 变量 进程映像 类型限定符进程映像变量类型限定符所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部