C语言的标准函数库与内存管理有关的函数从功能上分为两类:一类是系统对内存操作的函数,例如,读内存的函数、写内存函数,如从指定地址向内存写一个字节,一个字或向内存读一个字节或一个字操作;另一类是供用户动态使用内存的函数,例如,分配C程序一块存储区,并将该区清零函数;
1.动态内存分配函数
假如欲设计一个C程序,要求从一个文件读取一组数据并存放在数组中。如果无法预先知道文件中数据的确切数量,或者在再次运行时文件的数量发生变化,那么就需要在程序中把数组定义得足够大,才能适应上述情况。但这样做往往导致内存空间的浪费。动态分配内存可使程序在执行过程中获得需要的内存空间,以便更有效地利用内存空间。现将常用内存管理函数及其使用分别介绍于下:
(1)calloc()函数
功能
该函数是分配给C程序一块存储区,并将该存储区消零。程序在调用该函数时需要引用两个参数,分别指出程序分配对象个数和每个对象所需内存空间的字节数。calloc函数返回一个内存储区的字符指针,指向所分配内存区域的起始位置。若函数调用失败,返回NULL。调用格式calloc(number,size);
说明
调用此函数后,可占用从内存地址number开始的size个字符长度的连续内存空间,函数返回指向该空间起始位置的指针。
当内存空间不够分配时,calloc()返回空指针。因此,calloc()是一个返回值为指向字符的指针的函数。即
char *calloc();
其中number、size为无符号整数,即
unsigned int number size;
应用举例
应用calloc()函数从堆中申请255个字节的存储区,并向该区输入输出字符串,可编写如
下程序实现:
#include #defint N 255 #define S 1 main() extern char *calloc() extern char *fgets(); extern int fputs(),free(); char *buffer; buffer=calloc(N,S); if (!buffer) abort("Ug,too big \n"); fputs ("Enter data follwed by Ctrl-Z\n),stdout); while (fgets(buffer,N,sldin)) fputs (buffer,stdout); free(buffer); }
(2)malloc()函数
调用格式
malloc(Size);
功能
该函数被调用后,可占用预先指定了的内存区中的size个字符长度的连续内存空间,它允许程序按需要分配内存,而且恰好分配所需的大小。
说明
如果该函数调用成功,返回size空间的第一个字节的地址,当内存空间不够分配时,返回
NULL。它也是一个返回值为指向字符的指针函数,即:
char *malloc();
size也是无符号数,即;
unsigned int size;
malloc()与calloc()的区别是,malloc()只能在指定的内存空间中占用size个字符长度的连续空间,而calloc()可在任意的内存空间占用size个字符长度连续空间,这个内存空间的起始位置在调用函数calloc()时,临时指定。
应用举例
使用malloc()函数从堆中分配255个字节存储区,并对该区清零。
可编写如下程序实现:
#include main() { extern char *malloc(); extern int free(); char *buf ; unsigned number-bytes; int i; number-bytes=255; buf=malloc(number-bytes); printf("%s\n",buf); for(i=0;j *(buf+j)=EOS; printf("%s\n",buf); free(buf); } }
(3)free()函数
调用格式
free(pointer);
功能
该函数释放由calloc()或malloc()函数分配的存储空间,以便下次重新分配,以提高内存资源的使用效率。
说明
函数free()的调用需要一个指定释放内存空间的指针参数,在程序中应为字符型指针,
即:
char *pointer;
如果释放成功,函数free(pointer)返回值为零:当pointer参数为无效指针,返回值为-
1。
(4)rcalloc()函数
调用格式
rcalloc(pointersize);
功能
该函数用于改变callc()或malloc()所占用的内存区的大小,即将calloc()或malloc()
指定的size数改为rcalloc()指定的size指定的size数。
说明
该函数调用成功返回由pointer指针变量所指向的地址;当内存空间不够分配时,返回值为0。当不需要占用的内存空间时,用free()或cfree()释放。
2.内存读写函数
(1)peek()函数
功能
从内存指定的段偏移地址单元中读一个字。
格式
int peek ( unsigned segment,unsigned offset);
说明
peek()函数返回相应地址上的一个字的内容。
内存各地址是以段地址:偏移地址的格式。例如,0070:0000是绝对地址×’0700’。
应用实例
利用peek()函数,读取40:13单元的内容(此单元的一个字记录着系统存储器总容量,以KB为单位)并显示到屏幕上。可编写如下的程序实现:
#include #include #define SEGMENT 0X0040 #define OFFSET 0X0013 main() { int value=0; value=peek(SEGMENT,OFFSET); printf("\n The RAM is %d K.",value); getchar(); exit(0); }
(2)peekb()函数
功能 从内存指定的段:偏移中读取一个字节。
格式 char peekb(unsigned segment,unsigned offset);
说明 peekb()函数返回相应地址上的一个字节的内容。
应用实例 读取0X40:0X11处的一个字节,并分析其硬件设备的配置情况。可编写如下程序实现:
#include #include #iclude main() { char value=0; char va; printf("\n 当前机器的硬件配置"); value=peekb(0X40,0X11); if (Value & 1); printf ("\n DMA芯片已被安装"); else printf("\n DMA芯片没有安装"); if (value & 16); printf("\n 游戏卡已经安装"); if (value & 32); printf("\n 串行打印机已经安装"); va=value>>6; printf("\n 打印机安装的数目为%d,va); }
(3)poke()涵数
功能 向内存中写一个字。
格式 void poke ( unsigned segment,unsigned offset,int value);
说明 其中segment为要写入内存的段地址。offset为要写入内存的偏移量。value为要写入内存的值。
由于poke()函数有修改内存数据的能力,所以使用此函数时一定要注意,如果操作错误,其结果常常是死机。出现此类错误的原因多是由于指定的段地址、偏移地址的数值不正确或没有赋予初值,再有就是所写的数值不被系统所承认。
(4)poded()函数
功能 向内存中写一个字节。
格式 void poke (unsigned segment,unsigned offset,char value);
说明 其中segment为要写入内存的段地址,offset为要写入内存的偏移量。value为要写入内
存的值。
应用实例
从段地址100H处开始写内存5个字的数据,然后逐个字读取。可编写如下的程序实现:
#include main() { extern int peek(); extern int poke(); unsigned offset,segment; int word=0x0000; int i; segment=0x100; putchar("/n"); for(offset=0;offset<10;offset++) poked(offset,segment word++); for(offset=0;offset<10;offset) { word=peek(offset,segment); printf("peek(%xh,%xh)=%xh\n",offset segment,word); offset++=2 } }综合地使用poke(),pokeb(),peek(),peekb()这四个函数,可以达到控制操作系统的软件资源的目的。