9.动态内存管理

前面我们讲述的都是C语言中参与表达式的一些基本元素,这些基本元素都有一个共同特点,就是在声明时,C语言编译器就将它的内存地址固定好,比喻说一个int a变量,C语言编译器在生成汇编时候就将其地址给出。包括指针变量、数组、结构体,也是一样的。这些变量在内存中存在,不会产生内存错误。但接下来,我们会讲述另一种元素,这也是C语言的组成部分,它适用直接操作内存部分,通过这些直接操作内存函数,进行按需要在运行时进行内存分配,可以充分利用内存空间,带来运算效率的提高。当然也带来一定的内存管理风险。这里我们首先了解一下内存管理函数:

【1】分配内存空间函数malloc, calloc

    void* malloc(unsigned int size) 分配一个长度为size的连续空间,返回起始地址类型为void指针,当然你可以将这个分配好的指针强制转换为你所定义的类型。未成功是NULL

   void *calloc(unsigned n,unsigned size)同前面类似,但分配是n个长度为size的连续空间。常用于动态数组。

【2】释放内存空间函数free

      void free(void *p) 释放由p指向的内存区,这个p必须是由malloc或calloc返回的值 。

下面结合链表来讨论一下动态存储分配的实现。链表大家可能都知道,就是由很多节点组成的一个表结构,其中前一个节点保存后一个节点的地址,这样从逻辑上就是将所有节点像一个链子一样串起来。

image

image

10.共用体,同前面结构体类似,也是为了合理使用内存空间而设计的一种类型结果,共用体,命名用union定义,用来表示成员变量占用同一段内存空间。

image

共用体和共用体变量的声明方式和结构体及结构体变量声明方式完全一样,但是有一些特殊性质是共用体所独有的。如下所示:

【1】共用体分配内存只分配一个成员空间,这个成员是所有成员中需要内存最大的。结构体是每个成员都要分配空间。

【2】共用体所有成员的地址都一样,存储的内容都一样,只是在不能的上下文中表示不同的涵义。

【3】共用体是无法赋值,也无法初始化,其成员变量也是一次只能使用一个,同时使用两个实际上没有意义。

【4】共用体变量名称在编译器是不分配内存地址的,因此,不能作为函数参数,也不能返回,但对共用体变量指针可以使用。共用体可以作为一个复合类型出现在结构体中。

image

11.枚举类型 同前面共用体类似,枚举更死,所有变量的取值限定在一个有限范畴内。如一个星期七天可采用如下几种方式声明与变量定义。

enum weekday {sum,mou,tue,wed,thu,fri,sat};

enum weekday a,b,c;

enum weekday{sun,mou,tue,wed,thu,fri,sat}a,b,c;

enum{sun,mon,tue,wed,thu,fri,sat} a,b,c;

枚举类型是一种基本数据类型,它默认都是int值,你可以指定enum{sun=0,mon,tue,wed,thu,fri,sat}a,b,c;枚举元素是常量,因此,不能改变。

12.typedef类型重定义 同define不一样,define定义的是完全替换,是在预处理时进行的,typedef是类型别名,定义格式如下 typedef int Integer ;注意结尾一定要有;这与#define不同。用typedef可以重定义很多类型。

【1】基本类型 typedef int INTEGER;

【2】结构体  typedef struct {

                     int month;

                     int day;

                     int year;}DATE;

【3】数组类型 typedef int NUM[100];

【4】指针类型 typedef char* STRING;

【5】函数指针类型 typedef int (*pointer)();

image