C语言编程法式的内存怎样结构

  • 时间:
  • 浏览:47
重点关注以下内容:

  C语言法式在内存中各个段的组成

  C语言法式毗连历程中的特征和常见错误

  C语言法式的运行方式

  一:C语言法式的存储区域

  由C语言代码(文本文件)形成可执行法式(二进制文件),需要经由编译-汇编-毗连三个阶段。编译历程把C语言文本文件天生汇编法式,汇编历程把汇编法式形成二进制机械代码,毗连历程则将各个源文件天生的二进制机械代码文件组合成一个文件。

  C语言编写的法式经由编译-毗连后,将形成一个统一文件,它由几个部门组成。在法式运行时又会发生其他几个部门,各个部门代表了差别的存储区域:

  1.代码段(Code或Text)

  代码段由法式中执行的机械代码组成。在C语言中,法式语句举行编译后,形成机械代码。在执行法式的历程中,CPU的法式计数器指向代码段的每一条机械代码,并由处置惩罚器依次运行。

  2.只读数据段(RO data)

  只读数据段是法式使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。

  3.已初始化读写数据段(RW data)

  已初始化数据是在法式中声明,而且具有初值的变量,这些变量需要占用存储器的空间,在法式执行时它们需要位于可读写的内存区域内,并具有初值,以供法式运行时读写。

  4.未初始化数据段(BSS)

  未初始化数据是在法式中声明,可是没有初始化的变量,这些变量在法式运行之前不需要占用存储器的空间。

  5.堆(heap)

  堆内存只在法式运行时泛起,一样平常由法式员分配和释放。在具有操作系统的情形下,若是法式没有释放,操作系统可能在法式(例如一个历程)竣事后接纳内存。

  6.栈(stack)

  栈内存只在法式运行时泛起,在函数内部使用的变量、函数的参数以及返回值将使用栈空间,栈空间由编译器自动分配和释放。

  C语言目的文件的内存结构

  看一个例子:

  int a = 0; //全局初始化区,。data段

  static int b=20; //全局初始化区,。data段

  char *p1; //全局未初始化区 .bss段

  const int A = 10; //.rodata段

  void main(void)

  {

  int b; //栈

  char s[] = "abc"; //栈

  char *p2; //栈

  static int c = 0; //全局(静态)初始化区 .data段

  char *p3 = "123456"; //123456\0在常量区,p3 在栈上。

  p1 = (char*) malloc(10);//分配得来的10和20个字节的区域就在堆区

  p2 = (char*) malloc(20);

  strcpy(p1, "123456"); //123456\0 在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方

  }

  代码段、只读数据段、读写数据段、未初始化数据段属于静态区域,而堆和栈属于动态区域。代码段、只读数据段和读写数据段将在链接之后发生,未初始化数据段将在法式初始化的时间开发,而堆和栈将在法式的运行中分配和释放。C语言法式分为映像和运行时两种状态。在编译-毗连后形成的映像中,将只包罗代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在法式运行之前,将动态天生未初始化数据段(BSS),在法式的运行时还将动态形成堆(Heap)区域和栈(Stack)区域。一样平常来说,在静态的映像文件中,各个部门称之为节(Section),而在运行时的各个部门称之为段(Segment)。若是不详细区分,可以统称为段。

  知识点:

  C语言在编译和毗连后,将天生代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在运行时,除了以上三个区域外,还包罗未初始化数据段(BSS)区域和堆(Heap)区域和栈(Stack)区域。

  二:C语言法式的段

  1.代码段(code或text)

  代码段由各个函数发生,函数的每一个语句将最终经由编绎和汇编天生二进制机械代码(详细生生哪种系统结构的机械代码由编译器决议)。

  2.只读数据段(RO Data)

  只读数据段由法式中所使用的数据发生,该部门数据的特点是在运行中不需要改变,因此编译器会将该数据段放入只读的部门中。C语言中的只读全局变量,只读局部变量,法式中使用的常量等会在编译时被放入到只读数据区。

  注重:界说全局变量const char a[100]={"ABCDEFG"};将天生巨细为100个字节的只读数据区,并使用“ABCDEFG”初始化。若是界说为:const char a[ ]={"ABCDEFG"};则凭据字符串长度天生8个字节的只读数据段(另有’\0’),以是在只读数据段中,一样平常都需要做完全的初始化。

  3.读写数据段(RW Data)

  读写数据段表现了在目的文件中一部门可以读也可以写的数据区,在某些场所它们又被称为已初始化数据段,这部门数据段和代码段,与只读数据段一样都属于法式中的静态区域,但具有可写性的特点。通常已初始化的全局变量和局部静态变量被放在了读写数据段,如: 在函数中界说static char b[ 100]={“ABCDEFG”};读写数据区的特点是必须在法式经由初始化,若是只界说,没初始值,则不会天生读写数据区,而会定位为未初始化数据区(BSS)。若是全局变量(函数外部界说的变量)加入static修饰,这表现只能在文件内使用,而不能被其他文件使用。

  4. 未初始化数据段(BSS)

  与读写数据段类似,它也属于静态数据区,可是该段中的数据没有经由初始化。因此它只会在目的文件中被标识,而不会真正称为目的文件中的一段,该段将会在运行时发生。未初始化数据段只在运行的初始化阶段才会发生,因此它的巨细不会影响目的文件的巨细。

  在C语言的法式中,对变量的使用另有以下几点需要注重:

  1.函数体中界说的变量通常是在栈上,不需要在法式中举行治理,由编绎器处置惩罚。

  2.用malloc,calloc,realloc平分配内存的函数所分配的内存空间在堆上,法式必须保证在使用free释放,否则会发生内存走漏。

  3.所有函数体外界说的是全局变量,加了static后的变量不管是在函数内部或外部都放在全局区。

  4.使用const界说的变量将放于法式的只读数据区。

  三:法式中段的使用

  下面用一个简朴的例子来说明C语言中变量和段的对应关系。C语言法式中的全局区(静态区),现实对应着下述几个段:RO Data; RW Data ; BSS Data.

  一样平常来说,直接界说的全局变量在未初始化数据区,若是该变量有初始化则是在已初始化数据区(RW Data),加上const则将放在只读数据区。

  const char ro[ ] = {"this is read only data"}; //只读数据区

  static char rw_1[ ] ={"this is global read write data"}; //已初始化读写数据段

  char BSS_1[ 100]; //未初始化数据段

  const char *ptrconst ="constant data"; //字符串放在只读取数据段

  int main()

  {

  short b; //在栈上,占用2个字节

  char a[100]; //在栈上开发100个字节, 它的值是其首地址

  char s[ ]="abcdefg"; //s在栈上,占用4个字节,"abcdefg"自己放置在只读数据存储区,占8个字节

  char *p1; //p1在栈上,占用4个字节

  char *p2="123456"; //p2 在栈上,p2指向的内容不能改,“123456”在只读数据区

  static char rw_2[ ]={"this is local read write data"};//局部已初始化读写数据段

  static char BSS_2[100]; //局部未初始化数据段

  static int c = 0; //全局(静态)初始化区

  p1=(char *)malloc(10 * sizeof(char ) ); //分配内存区域在堆区

  strcpy(p1,"xxxx"); //“XXXX”放在只读数据区,占5个字节

  free(p1); //使用free释放p1所指向的内存

  return 0;

  }

  读写数据段包罗了忆初始化的全局变量 static char rw_1[ ]以及局部静态变量static rw_2[ ].其差异在于编绎时,是在函数内部使用的照旧可以在整个文件中使用。对于rw_1[] 无论有无static 修饰,其都将被放置在读写数据区,只是能否被其它文件引用与否。对于后者就纷歧样了,它是局部静态变量,放置在读写数据区,若是没static修饰,其意义完全改变,它将会是开发在栈空间的局部变量,而不是静态变量,在这里rw_1[],rw_2[]后没详细数值,表现静态区巨细同后面字符串长度决议。

  对于未初始化数据区BSS_1[100]与BSS_2[100],其区别在于前者是全局变量,在所有文件中都可以使用;后者是局部变量,只在函数内部使用。未初始化数据段不设置后面的初始化数值,因此必须使用数值指定区域的巨细,编绎器将凭据巨细设置BSS中需要增添的长度。

  栈空间主要用于以下3数据的存储:

  1.函数内部的动态变量

  2.函数的参数

  3.函数的返回值

  栈空间是动态开发与接纳的。在函数挪用历程中,若是函数挪用的条理比力多,所需要的栈空间也逐渐加大,对于参数的通报和返回值,若是使用较大的结构体,在使用的栈空间也会比力大。

本栏文章均来自于互联网,版权归原作者和各公布网站所有,本站网络这些文章仅供学习参考之用。任何人都不能将这些文章用于商业或者其他目的。( Pfan.cn )