变量类型,变量作用域,变量存储空间,变量生命周期

变量类型

常量是不可变的值,可以用宏来定义,比如 #define PI 3.14

变量的值是可以变化的,由于编程的不同需求,对变量有各种要求,

  比如:变量的生命周期,变量的初始状态,变量的有效区域(作用域),变量的存储地和存储区域的大小。

为了满足这些不同的编程需求,C语言发明者设置了以下变量:

  1 不同数据类型的变量。比如 char,int,float等。(变量在内存中占用地址大小由数据类型决定)

  2 全局变量

  3 局部变量

  4 静态变量:包括静态全局变量和静态局部变量

  5 寄存器变量

  6 外部变量 

C语言中,除了基本类型外,开发者可以通过typedef来定义自己需要的数据类型。比如:

  typedef int INT;

  typedef unsigned int UINT;

  typedef struct student

  {

    char *name;

    int age;

  }STUDENT;  

  如果结构体student不用typedef重定义的话,定义结构体变量时:struct student stu1;  

  使用typedef重定义以后,我们只需要STUDENT stu1;即可。

  1 全局变量。在函数外定义,可被所有函数使用。但是在多线程访问时,需要注意多线程安全问题。

  2 局部变量。在函数内部声明。只有在函数执行时,局部变量才存在,函数执行完局部变量就消失。

  3 静态变量。分配在内存中的数据段中,在C程序运行的整个过程中一直保留,静态变量可以定义成静态全局变量和静态局部变量。

    ①静态全局变量在程序的整个运行期间都存储且内存地址不会改变。

    ②静态局部变量只在声明它的函数内有效,且在下一次调用时还保留上次调用结束时的值(只初始化一次)。

  4 寄存器变量。 寄存器变量存放在CPU的寄存器中,使用寄存器变量比内存变量操作速度快得多。

    只有整型和字符型变量可以定义为寄存器变量。比如:

    register int i;

    register char c;

    ①由于CPU中寄存器有限,尽量减少使用寄存器的数量和占用时间,用完马上释放。

    ②寄存器变量不能定义为全局变量,也不能定义在结构体和类中。

    ③如果寄存器已经无可用资源,寄存器变量将转化为普通局部变量。

extern:

  在大型程序中,会将一个大型的程序分成多个独立的模块和文件分别编译,然后统一链接在一起。为了解决全局变量和函数的共用问题,

引入了extern关键字。只需要在一个文件中定义全局变量和函数,在另一个文件中要用到这些变量和函数时,只需要将那个文件中的变量和

函数说明复制过来,然后在前面加上extern就可以。这样就等于告诉编译器,这些变量和函数已经在别的文件中定义。

变量的存储空间

  代码和数据,都要加载到内存中,才能被运行和访问。X86系统中,内存的有效范围为4GB。

  ①高2GB内存地址为内核空间,用来存放内核的代码和数据

  ②低2GB为用户空间,运行进程的用户态代码,且低2GB的内存是进程私有空间,一个进程不能跨进程访问别的进程空间的用户态地址。

如图所示,程序在内存中分为如下几部分:

1 .text 代码段,这段是存放代码的

2 .rdata 只读数据段,不能修改,存放常量,字符常量,const常量。

3 .data 数据段 存放已经初始化好的全局变量和静态变量

4  .bss 存放未初始化的全局变量和静态变量

  PS:.rdata,.data,.bss都是存放数据的段。.rdata段和.data段的值都在编译的时候就确定了,并且将值编译进了

  可执行文件,经过反汇编就可以找到。已初始化的全局变量放在.data段,未初始化的变量放在bss段。

5 .stack 栈段,栈中存放普通的局部变量(非静态局部变量),形参,返回地址等。栈的大小有限制:

  windows应用层栈大小默认为1MB;普通内核栈的大小是固定的,由系统根据CPU架构决定,X86系统上12KB,X64系统24KB,安腾系统32KB

  Linux应用层栈大小默认为10MB,内核栈大小4KB或8KB

6 堆: 可以存放任意数据

综上:

①全局初始化变量存放在静态存储区的.data段

②全局未初始化变量存放在静态存储区的.bss段

③局部变量存放在栈

④全局静态变量和局部静态变量存放在静态存储区的.data段和.bss段

⑤常量存放在静态区的.rdata段。.rdata区域是只读内存,不能修改

⑥寄存器变量存放在寄存器中 (如果寄存器资源不够,还是放在内存中)

变量的作用域

变量的作用域指变量能在代码什么地方可以被访问到。

1 全局变量: 所有程序中的代码都能访问。

  如果全局变量在一个源文件中定义,在另一个源文件中访问,需要用extern关键字导入。多线程访问全局变量注意安全问题

2 静态全局变量: 在同一个源文件中可以访问,不同源文件不可访问,也不能用extern来导入。

3 局部变量:只能在函数内部访问

4 静态局部变量:只能函数内部访问

5 寄存器变量:只能在函数内部访问

变量的生命周期

变量的生命周期是指变量在程序运行期间的有效时间

1 全局变量:整个程序运行期间有效

2 静态全局变量:整个程序运行期间有效

3 局部变量:函数范围内或代码块范围内有效

4 静态局部变量:整个程序运行期间有效

5 寄存器变量:函数范围内或代码块范围内有效

  

习题:分析下列程序中每个变量的存储位置,作用域,与生命周期 
int a = 0; 
char *p1; 
static int x = 10; 
void main(void) 

    int b = 0; 
    char s[] = "123"; 
    char *p2; 
    char *p3 = "hello, world"; 
    static int c =0; 
    p1 = (char *)malloc(128); 
    p2 = (char *)malloc(256); 
    free(p1); 
    free(p2); 


分析与解答:下面给出了上面各变量的类型,存储,作用域和生命周期的详细的归纳:
int a = 0; //全局初始化变量 
char *p1; //全局未初始化变量 
static int x = 10;//全局初始化静态变量 
void main(void) 

    int b = 0; //局部变量 
    char s[] = "123"; //s局部变量,字符数组,用"123"字符串常量进行初始化 
    char *p2; //局部变量 
    char *p3 = "hello, world"; //p3局部变量,字符指针,指向"hello, world"字符串常量 
    static int c =0; //静态局部变量,已初始化 
    p1 = (char *)malloc(128); //p1,p2指向堆 
    p2 = (char *)malloc(256); 
    free(p1); //显示释放p1,p2指向的堆内存 
    free(p2); 

  

原文地址:https://www.cnblogs.com/fengxing999/p/10956274.html