C语言中储存类别与内存管理的深入理解

储存类别

C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念。

1. 基础概念

对象:不同于面向对象编程中的对象的含义,C语言是面向过程编程,不存在这样对象的概念,这个对象指的是值储存所占据物理内存空间。

左值:左值是可以指定对象的表达式,它的最简单形式即为标识符,复杂的可以为为指针之类。一个表达式成为左值的前提是它确实指定了一块作为对象的储存空间,例如:

 int a = 1;//a作为标识符,也作基础表达式,指定了一个对象,是左值
 int *pa = &a;//pa同a也指示了一个储存地址对象,是一个左值;*pa是一个表示式,指示了a相同的对象也是一个左值
 int arr[5] = {0};
 arr+a*3;// 这段表达式就不是一个标识符,也不是一个左值了,因为它没有指定内存上的任意位置
 *(arr + a * 3);// 不同于上面的,这也是一个左值,因为它确实指定了内存上的位置

左值分为可修改左值和不可修改左值。

我们通常用储存期来描述对象,表明对象在内存中留存的时间。用标识符指定对象时,使用作用域和链接来描述标识符,其中作用域表明标识符可以可以被程序使用的范围,链接表明程序的哪些其他文件也可以使用它。

不同的储存类别之间的区别即在于它们的储存期、作用域和连接形式的不相同。我们来分别了解他们一下。

储存期:储存期分为静态储存期,自动储存期,线程储存期和动态分配储存期(线程储存期暂时不多赘述),它们分别对应不同的在内存中的储存位置,也有不同的特点。

静态储存期:对应静态存储位置,它在程序开始运行时就被分配,这段空间不可增加和减少,所以从程序开始运行到停止运行,静态储存期的数据一直存在。通常在函数外的变量和static表示的变量具有静态储存期。

自动储存期:对应栈空间,它随着程序的运行可以自动进行分配,增加或减少。程序进入到一个块为其中的变量分配栈空间,退出一个块后则会释放相应的空间。一般的创建的变量都具有自动储存期。

动态分配储存期:对应堆空间,它需要通过特殊的语法进行申请,申请后也需要主动进行销毁,存在时间为从申请内存开始到主动释放内存为止。需要通过专门的语句来获得具有动态分配储存期的变量。

作用域:一个变量能被使用的范围称为作用域,作用域分为 块作用域、函数作用域、函数原型作用域和 文件作用域。

块作用域:由一个花括号开始到与之对应的花括号为止,其中的变量都具有块作用域,一般情况下任何在块内的定义的变量可以在块内任何位置使用,但是不可以在块外进行使用。(特例后面会举出),而且对于内部块也可以定义与外部块同名的变量,这时候内部块将隐去向内隐去外部块的同名变量,在内部使用自己定义的该变量。

函数作用域:针对的是goto语句标签,一个标签首次出现在含糊内层,它的作用域将会延伸至整个函数,这表示我们不能使用同名的标签。

函数原型作用域:对于函数的声明,该作用域开始与形参定义处知道函数函数原型结束。编译器只注重形式参数的类型而不会注意具体的变量名,甚至可以不使用变量名。

文件作用域:声明在函数外的变量具有文件作用域,他们可以在同一源文件下的任何块和函数中使用,具有文件作用域的变量也被称为全局变量。

对于分别属于同类型作用域但是不同一个作用域的变量它们可以任意重名,例如不同块的函数中变量属于不同块他们可以重名。对于具有文件作用域的变量它们对于所属的文件块都有作用,所以不建议块中变量与全局变量重名,但是在重名后块使用对应名称变量时将以块中自身定义的变量为准。

 #include <stdio.h>
 ​
 void showA(int a, int type) {
 switch (type) {
 case 1:
 printf("outer : ");
 break;
 case 2:
 printf("inter : ");
 break;
 case 3:
 printf("circle : ");
 default:
 ;
 }
 printf("a = %d\n", a);
 }
 ​
 int main (void) {
 int a = 1;
 showA(a, 1);
 {
 int a = 2;
 showA(a, 2);
 }
 showA(a, 1);
 while (a++ < 5) {
 int a = 5;
 showA(a, 3);
 }
 showA(a, 1);
 return 0;
 }
 ​
 ​
 /**
 outer : a = 1
 inter : a = 2
 outer : a = 1
 circle : a = 5
 circle : a = 5
 circle : a = 5
 circle : a = 5
 outer : a = 6
 * **/

我们发现在在外部a为在外部定义的值,a输出为1;第一块内部,a读取的是内部的a的值,这一点没有任何问题;然后我们到外部,我们再让程序输出a值,仍然为2,没有问题;但是进入循环后,我们发现很奇怪的现象,通过输出我们发现循环执行了4次,很明显这是基于外部的a,但是内部的a在输出时却总是显示内部的a,这一点是因为:内部循环定义的a作用域只在块内,并不会作用于循环条件判断的部分,所以在进行循环条件判断时始终使用外部的a。注意递增条件一定要在循环判断条件中,否则循环将变成死循环。但是,没有必要使用同名变量。

链接:链接是程序中变量可以被其他文件使用的描述,有三种类型的链接:外部链接、内部链接和 无链接。

如果一个变量具有文件作用域它才可能具有外部链接和内部链接,其他变量都是无链接的。在具体了解内部链接和外部链接之前,我们先理解下 翻译单元的概念。

翻译单元:我们经常使用#include指令来包含头文件,C通过预处理将对应头文件内容直接替换掉该条命令,他们虽然表面上看起来不是一个文件但是被编译器看做了一个文件,这个文件就被称为一个翻译单元,一个具有文件作用域的变量它的实际可见范围就是整个翻译单元。一个翻译单元由一个源文件和多个它所包含的文件组成。

所以外部链接可以在多文件程序中使用,而内部链接只可以在一个翻译单元使用。区别二者在于是否使用了储存类别说明符static,使用了static则为内部链接,反之则为外部链接。

 //main.c 文件
 #include <stdio.h>
 ​
 int main (void) {
 extern int a;// 声明,让编译器在别处查找a的定义
 // extern int b;
 // printf("b = %d", b);这一段不可使用,因为b只具有内部链接,不可在其他源文件访问,运行
 // 报错
 printf("a = %d", a);
 return 0;
 }
 ​
 /**
 a = 5
 * **/
 // 和它一同编译的another.c文件
 int a = 5;// 具有外部链接,可以在多个源文件之间进行共享
 static int b = 2;// 具有内部链接,只能在一个源文件内共享

在这里我们使用了外部链接变量a,在两个翻译单元之间实现了变量的传递。其中main.c文件为了调用变量a必须有extern声明语句,这段语句声明了一个int型变量a但是并不会为它分配内存,使用它只是为了告诉编译器在别处寻找变量a的定义,这是必不可少的,否则程序将会报错。

 // main.c文件
 #include <stdio.h>
 #include "main.h"
 ​
 int main (void) {
 extern int a;
 printf("a = %d", a);
 return 0;
 }
 ​
 /**
 a = 7
 * **/
 // main.h文件
 static int a = 7;

不同于源文件,对于头文件,通过#include指令包含头文件,编译器将自动将对应文件内容替代到对应位置,它们属于同一个翻译单元,所以及时具有内部链接的变量仍可以使用。

2. 储存类别分类

介绍了一些基础概念后我们来根据这些基础概念对于储存类别进行分类:

储存类别 储存期 作用域 链接 声明方式
自动 自动 块内声明
寄存器 自动 块内声明,加入关键字register
静态外部链接 静态 文件 外部 函数外
静态内部链接 静态 文件 内部 函数外,加入关键字static
静态无链接 静态 块内声明,计入关键字static

下面我呢来分别具体对于每种类型所对应的变量进行说明。

3. 自动变量

自动变量具有自动储存期,块作用域,无链接,在块内进行声明即可。自动储存期意味着它在开始执行块时被创建,在对应块到结尾时被销毁,不能再被通过任何途径访问;块作用域表明只能在块中使用变量名对于变量进行访问,但是在处于变量可使用的储存期内(这点必要,因为我们无法控制编译器的回收机制),我们也可以通过指针传递地址的方式来继续使用;无链接表明不能再其他文件中对于该变量进行访问。

对于自动变量,默认情况下声明的变量都具有这样的储存类别,但是有时候为了更明显的表现意图,并且在外部具有同名变量时,为了更好覆盖它,表明自己变量的自动储存类型,可以使用关键字auto,例如:

 #include <stdio.h>
 ​
 int a = 1;
 ​
 int main (void) {
 auto int a;// int a;也是等价
 printf("a = %d", a);
 return 0;
 }

在外部有同名变量时,使用auto关键字还是用来标识a作为块内的自动变量,覆盖外部的a,即使不加auto也是可以的,但是使用后可以起到更好的标识性。

4. 寄存器变量

寄存器变量在多个方面与自动变量相同,不同在于自动变量通常储存在计算机内存中,而寄存器变量储存在计算机CPU的寄存器中,因此它具有高效的运算率,而且因为它在寄存器中所以无法获得其地址。通过在变量定义中使用register修饰既可以声明寄存器变量:register int a;

但是,值得注意的是,使用register企图创建寄存器变量是一种请求而不是命令,编译器很可能不会通过你的请求,而且寄存器也有可能没有足够大空间储存double类型变量,所以可以声明register的数据类型也是有限的。即使失败,也能够创建相应的自动变量,但是我们仍然不能获得其地址。

5. 具有块作用域的静态变量

具有块作用域的静态变量,对应的储存类别为静态无链接,其具有静态储存期,块作用域和无链接。它在程序开始运行时被创建,程序结束后被销毁。只在它被定义的块内调用,无法被其他文件访问。

相较于自动变量,它只是拥有了静态储存期,所以我们使用static类别修饰符获得该类型变量static int a;。值得注意的是,由于该变量具有静态储存期,所以它始终储存在系统中的某一段内存空间中,我们可以利用指针在块外的区域对于该变量进行访问。

 #include <stdio.h>
 ​
 int* fun();
 ​
 int main (void) {
 int *p = fun();
 *p += 2;
 fun();
 return 0;
 }
 ​
 int *fun() {
 static int a = 1;
 printf("a = %d\n", a);
 return &a;
 }
 ​
 /**
 a = 1
 a = 3
 * **/

通过上面的运行结果我们发现通过函数返回指向静态变量的指针,我们可以对静态变量进行访问和修改,这使得我们在块外对块内无链接的静态变量进行访问。

6. 内部链接的静态变量

内部链接的静态变量对应储存类别为静态内部链接。它具有静态作用期,文件作用域和内部链接。它在程序开始被创建,在同一个翻译单元内可以任意访问。在前面已经有它的用例。

7. 外部链接的静态变量

外部链接的静态变量对应储存类别为静态外部链接。它具有静态作用器,文件作用域和外部链接。大体上与内部链接的静态变量相同,但是它可以在多个翻译单元(多个源文件之间)进行共享。

但是仍有一些事项注意:

声明时可以显示初始化,但是必须使用常量进行初始化(对于sizeof表达式也是常量),如果未进行初始化,无论如何它将被初始化为0。

 #include <stdio.h>
 ​
 int a;
 int b = 3;
 int c = 3 * sizeof b;
 // int d = 3 * a;非常量无法初始化
 char d;
 ​
 int main (void ) {
 printf("a = %d\n", a);
 printf("b = %d\n", b);
 printf("c = %d\n", c);
 printf("d = %d d = %c\n", d, d);
 return 0;
 }
 ​
 /**
 a = 0
 b = 3
 c = 12
 d = 0 d =
 * **/

如何跨文件使用具有外部链接的变量?正常情况下直接使用将会报错,我们需要通过引用性声明来使用,通过extern关键字来实现,在变量声明前加上关键字,编译器就会明白根据指示在其他源文件中查找变量的声明,这样的声明不会申请新的内存,也不可以进行赋值。

 // main.c
 #include <stdio.h>
 ​
 int main (void ) {
 // extern int a = 1;是不能赋值的
 extern int a;
 printf("a = %d\n", a);
 return 0;
 }
 ​
 /**
 a = 5
 * **/
 // anothor.c
 int a = 5;

8. 储存类别说明符小结

C中储存类别说明符有多个,并且不同说明符在不同位置也有不同意义。一共有一下说明符:auto、extern、register、static、_Thread_local和typedef。最后者被归为此类属于一些语法上的原因。它们大多都是单独使用,但是_Thread_local可以和static和extern一起使用。

auto表明变量具有自动储存期,在块内的变量默认具有自动储存期,使用auto只是明确表示要使用与外部变量重名的局部变量的意图。

register表明希望将变量储存在寄存器中,希望以最快的速度读取变量,同时不希望获得该变量的地址。

static表明变量具有静态储存期,它并不改变块内变量的链接类型,但是对于快外的变量,将会限制它的链接类型为内部链接。

extern表明该变量定义在别处,希望编译器在别处查找,包含extern的声明具有文件作用域,那么变量的定义一定有外部链接;如果只是具有块作用域,那么变量的定义可以有内部链接,也可以外部链接。

9. 储存类别的选用

到最后了,我们来考虑下储存类比的选用,一般情况下我们只建议使用自动储存类别,使用外部变量在程序间通信是方便的但同时也是危险的,所以我们希望尽力避免使用,同时我们要明白保护性程序设计的“按需知道”法则,尽量在函数内部解决该函数的任务,只共享哪些必须共享的变量。

动态内存管理

C语言除了自身建立了自动储存类型和静态储存类型来进行自主的内存管理来方便我们编程,同时也给我提供了一些工具是的我们能够进行灵活的内存使用和管理,我们通过了解使用C语言的内存分配来具体了解。

1. 内存分配之malloc

malloc函数声明在头文件stdlib.h中,其函数原型为

void* malloc(size_t size);

我们通过参数size(单位字节)来获得指定大小的一段空间同时返回指向该空间的空指针,我们可以通过强制类型转换来获得我们需要类型的指针,如果申请内存失败,它就会返回空指针NULL。我们通过具体的用例来了解它的使用:

 #include <stdio.h>
 #include <stdlib.h>
 ​
 int main (void) {
 int *a = (int *)malloc(sizeof(int));// 创建一个int
 int *b = (int *)malloc(sizeof(int)*5);// 创建长度为5的数组
 *a = 4;
 for (int i = 0; i < 5; ++i)
  b[i] = i*i;
 printf("*a = %d\n", *a);
 for (int i = 0; i < 5; ++i)
  printf("b[%d] = %d\n", i, b[i]);
 free(a);
 free(b);
 return 0;
 }
 ​
 /**
 *a = 4
 b[0] = 0
 b[1] = 1
 b[2] = 4
 b[3] = 9
 b[4] = 16
 * **/

我们发现可以通过内存申请可以灵活的创建变量和数组,然后对他们进行访问和修改,但是千万不要忘记调用free函数接受被分配空间的指针,来释放对应空间。不然大量的空间将无法被再利用造成内存的浪费,同时一些操作系统在程序运行结束后可能不会自动释放这些被分配的内存,甚至可能耗尽内存,产生可怕的 内存泄漏。

同时通过动态分配内存也有更加灵活的用途,例如创建变长数组:

 #include <stdio.h>
 #include <stdlib.h>
 ​
 int main (void) {
 int len;
 scanf("input the len: %d", &len);
 int *arr = (int *)malloc(sizeof(int) * len);
 return 0;
 }

通过这样一段程序我们就实现了,创建用户输入数字大小的整形数组。

2. 内存分配值calloc

calloc函数与malloc函数功能大体相同,它的函数原型:

void *calloc(size_t num, size_t size);

接受两个参数,第一个为希望分配的该大小的内存块数,第二个为希望一个空间大小(单位字节)。同样的我们要求在每次使用过后通过free函数将对应指针指向的分配的空间进行释放。

储存类别和动态内存分配

储存类别和内存分配有着密切可分的关系,我们来讲述一个理想中的模型:

程序将它的内存分为三个部分,一部分给静态变量使用;一部分给自动变量使用,最后一部分提供给动态内存分配。为什么这样分配呢?

静态变量使用的内存在程序编译时确定,在程序运行的整个周期都可以别访问,最后在程序结束时被销毁,所以我们可以单独使用一块区域对于其进行管理。

自动变量在进入对应变量定义的块时被分配空间,在离开块后被销毁。伴随着函数的调用和结束,自动变量使用的内存数量也对应的增加和减少,这部分内存通常使用栈来管理,新建的变量将按顺序入栈,销毁时按照相反的方向进行销毁。

使用动态分配内存的内容,他们创建于malloc或者calloc函数被调用的时候,在调用free函数被销毁,这些内存完全依赖于程序员自身的管理,我们可以在一个函数中创建它然后在另一个函数中销毁它。这样就使得这样的一部分内存被分配的支离破碎,有可能未分配的内存处于分配的内存之间,使用这样的内存往往是比使用栈来的更慢的。

我们通过一个程序来更好了解变量处于的空间:

 #include <stdio.h>
 #include <stdlib.h>
 ​
 static int a = 1;
 static int b = 2;
 ​
 int main (void) {
 static int c = 3;
 int d = 4;
 int e = 5;
 int f = 6;
 int *p1 = (int *)malloc(sizeof(int));
 int *p2 = (int *)malloc(sizeof(int));
 int *p3 = (int *)malloc(sizeof(int));
 printf("static: %p\n", &a);
 printf("static: %p\n", &b);
 printf("static: %p\n", &c);
 printf("auto: %p\n", &d);
 printf("auto: %p\n", &e);
 printf("auto: %p\n", &f);
 printf("dynasty: %p\n", p1);
 printf("dynasty: %p\n", p2);
 printf("dynasty: %p\n", p3);
 return 0;
 }
 ​
 /**
 static: 00405004
 static: 00405008
 static: 0040500C
 auto: 0061FF10
 auto: 0061FF0C
 auto: 0061FF08
 dynasty: 00791930
 dynasty: 007918B8
 dynasty: 007918C8
 * **/

可以发现不同类型的变量储存在不同地址附近。

总结

对于C中的变量我们可以通过类型和储存类别来描述,除此之外C新的标准也更新了一些特殊的修饰符const之类来修饰,灵活的使用他们能让程序运行的更有效率,实现更多的功能。

到此这篇关于C语言中储存类别与内存管理的文章就介绍到这了,更多相关C语言储存类别与内存管理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一文秒懂C语言/C++内存管理(推荐)

    C 语言内存管理指对系统内存的分配.创建.使用这一系列操作.在内存管理中,由于是操作系统内存,使用不当会造成毕竟麻烦的结果.本文将从系统内存的分配.创建出发,并且使用例子来举例说明内存管理不当会出现的情况及解决办法. 一.内存 在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明.例如在计算机中,一个视频播放程序与一个浏览器程序,它们的内存并不能访问,每个程序所拥有的内存是分区进行管理的. 在计算机系统中

  • 模拟实现C语言中的内存管理

    这里模拟了C语言中的内存管理,当我们要创建或者使用一个对象时,那么这个对象会调用retain方法,计数+1,当我们要释放对象,我们会调用free,这里注意要对计数记性判断,如果是0的话,那么就会销毁. #import <Foundation/Foundation.h> int cnt = 0; void fun (charchar * p) { printf("%c\n",p[0]); } charchar * retain1(charchar * p) { //retai

  • 通过一个小例子来简单理解C语言中的内存空间管理

    对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text).数据段(.data).BSS段(.bss),堆和栈组成,其中代码段,数据段和BSS段是编译的时候由编译器分配的,而堆和 栈是程序运行的时候由系统分配的.布局如下 在上图中,由编译器分配的地址空间都是在连接的时候分配的,而运行时分配的空间是在程序运行时由系统分配的 BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量和静态变量 (这里注意一个问题:一般的书上都会说全局变量和静态变量是会自动初始化

  • C语言中储存类别与内存管理的深入理解

    储存类别 C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念. 1. 基础概念 对象:不同于面向对象编程中的对象的含义,C语言是面向过程编程,不存在这样对象的概念,这个对象指的是值储存所占据物理内存空间. 左值:左值是可以指定对象的表达式,它的最简单形式即为标识符,复杂的可以为为指针之类.一个表达式成为左值的前提是它确实指定了一块作为对象的储存空间,例如: int a = 1;//a作为标识符,也作基础表达式,指定了

  • C语言深入细致讲解动态内存管理

    目录 为什么存在动态内存管理 动态内存函数的介绍 malloc free calloc realloc 常见的动态内存错误 对NULL指针的解引用操作 对动态开辟空间的越界访问 对非动态开辟内存使用free访问 使用free 释放一块动态开辟内存的一部分 对一块动态内存多次释放 对动态内存开辟忘记释放 柔性数组 小结 为什么存在动态内存管理 我们已经掌握的内存开辟方式有: int val = 20;//在栈空间上开辟四个字节 char arr[10] = { 0 };//在栈空间上开辟10个字节

  • C语言中结构体与内存对齐实例解析

    1.结构体类型 C语言中的2种类型:原生类型和自定义类型,结构体类型是一种自定义类型. 2.结构体使用时先定义结构体类型再用类型定义变量 -> 结构体定义时需要先定义结构体类型,然后再用类型来定义变量. -> 也可以在定义结构体类型的同时定义结构体变量. // 定义类型 struct people { char name[20]; int age; }; // 定义类型的同时定义变量. struct student { char name[20]; int age; }s1; // 将类型st

  • C语言中结构体的内存对齐规则讲解

    目录 1.结构体的内存对齐规则 2.例子 3.为什么存在内存对齐 4.如何修改默认对齐数 1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处. 2.其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处. 对齐数=编译器默认的一个对齐数与该成员大小的较小值.(VS中默认的对齐数是8) 3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数 )的整数倍. 4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最

  • go语言中值类型和指针类型的深入理解

    golang这个语言用起来和java. c#之类语言差不多,和c/c++差别比较大,有自动管理内存机制,省心省力. 然而,如果写golang真的按写java的习惯去写,也容易出问题,因为golang中有指针的概念,虽然这个指针是c/c++的自动化版本,但是却也有指针的特征,如果不熟悉其中原理,写出来的程序虽然不至于有运行BUG,性能却不友好. 因此,不能完全以写java的思路去写golang,一定要注意其中差别. 我们知道,在java之中,除了基本类型之外,所有的变量类型都是引用类型,你可以随意

  • C/C++语言中结构体的内存分配小例子

    当未用 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度对齐:当使用了 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度和 #pragma 指令指定的位数中的较小值对齐. #pragma 指令格式如下所示:#pragma pack(4)     // 或者 #pragma pack(push, 4) 举例如下:(机器字长为 32 位)    struct    {        char a;    }test;    printf("%d

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

  • C语言与C++内存管理超详细分析

    目录 一.内存 1.1 内存四区 1.2 使用代码证实内存四区的底层结构 二.malloc 和 free 2.1 malloc 和 free 的使用 2.2 内存泄漏与安全使用实例与讲解 三.new 和 delete 3.1 new 和 delete 使用 3.2 delete 与 delete[] 的区别 一.内存 在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明.例如在计算机中,一个视频播放程序与

  • Python深入学习之内存管理

    语言的内存管理是语言设计的一个重要方面.它是决定语言性能的重要因素.无论是C语言的手工管理,还是Java的垃圾回收,都成为语言最重要的特征.这里以Python语言为例子,说明一门动态类型的.面向对象的语言的内存管理方式.  对象的内存使用 赋值语句是语言最常见的功能了.但即使是最简单的赋值语句,也可以很有内涵.Python的赋值语句就很值得研究. a = 1 整数1为一个对象.而a是一个引用.利用赋值语句,引用a指向对象1.Python是动态类型的语言(参考动态类型),对象与引用分离.Pytho

随机推荐