C语言中常用malloc()和calloc()函数来动态地取得内存空间。
一、malloc()和free()函数
malloc()和free()函数是C语言中最常用的动态内存分配与释放函数。
malloc()的格式为:指针=malloc(空间大小);
例如:ptr=malloc(100);这个指令要求计算机分配连续的100Bytes空间。malloc()函数返回该空间的首地址,且存入ptr内。
free()的格式为:free(指针);//把指针所指区域释放掉
例子:char *p;
p=(char*)malloc(8);//开辟8个字节的存储空间,并把地址赋给指针p,通过指针p对该空间进行存取操作。
*p='L'; //存储字符,所分配空间的第0字节存储L
*(p+1)='o';//分配空间的第一字节存储字符'o'.
*(p+2)='v';
*(p+3)='e';
*(p+4)='\0';
puts(p);//输出字符串
free(p);//释放空间
注意:*(p+n)等价于p[n],(p+n)是地址,而*(p+n)就是取地址(p+n)的内容。
如上面程序中的*(p+1)='A';可写成p[1]='A';
malloc()函数的参数可以是常数、变量或表达式等。除了存放字符串外,malloc()也可取得空间来存储整数等数据。例如存储整数分配空间如下:
int *ptr;
ptr=(int *)malloc(sizeof(int)*4);
malloc()开辟空间存储4个整数数据,由于malloc()总传回第0字节的地址,且返回值必定是char*类型,所以要通过(int *)来强制转换为指向整型后存入指向整型的指针ptr.
当用malloc()函数分配空间时,若计算机无法提供足够的空间分配则会返回NULL指针。所以,若返回的指针为NULL,就表示可分配的剩余空间已不足。
----------------------------------------------------------------------------------------------
C语言动态分配系统
C语言的内存分配
C语言的内存分配有三种方式,即静态分配、动态分配和在栈上创建。
静态分配指在编译时在程序(进程)的数据段分配相应的空间给变量,如全局变量和静态变量,它们持续存在于进程的整个运行时,并且完全由编译器控制分配和释放。
在栈(Stack)上创建的内存也由编译器控制,用于存储函数的参数,非静态局部变量等。函数开始执行时,实参和局部变量被推入栈中;函数执行完成后,入栈的变量被推出栈。
动态分配(dynamic allocation)是程序在运行时根据实际需要从堆(Heap)上取得或交回内存的方法。所分配的内存由程序员控制,在运行时,编译器并不会自动删除它们,而是由程序员决定它们的生存期。
指针与动态内存分配/动态分配函数
C语言的指针为动态分配系统提供必要的支持。C的动态分配函数:
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nitems, size_t size);
void *realloc(void *block, size_t size);
void free(void * block);
malloc()分配一个size大小的内存空间,并且用一个void类型的指针指向这个空间,然后返回这个指针;如果堆中内存不足,函数失败,返回空指针NULL。
下面的代码在堆上分配1000字节,返回后,赋值给字符指针ptr;ptr指向这1000字节的首地址:
char *ptr;
int *iptr;
ptr = malloc (1000); /* 分配字节 */
iptr = malloc (50 * sizeof(int)); /* 为50整数分配内存 */
这里,malloc()函数的返回值在赋值给ptr和iptr时,并不需要使用强制类型转换(参《指针表达式》);但是,要注意,malloc()函数所分配的内存是未初始化的,即这块内存中的值是不确定的。
尽管堆中的自由内存一般都很大,但它仍然是有限的,因此分配函数可能失败,返回空指针;所以,在调用分配函数后,要对它的返回值进行检查,确保指针是有效的;否则可能导致程序瘫痪。
calloc ()同样是在堆上分配内存,但它所分配的空间大小是由nitems * size决定,即分配的内存量等于nitems * size。与malloc()函数相比较,calloc ()所分配的空间会被初始化为零,即用0填充。
realloc ()用于改变已经分配的内存空间的大小。本函数在C89和C99之间,存在一些不同。在C89中,realloc ()函数将先前分配的,由block指向的内存的大小改变为size的大小。size的值可以大于原来的值,也可以小于原来的值。在重新分配时,旧块(最大为size字节)中的内容被复制到新块中。在C99中,block是空闲的,并被分配了新块;新块包含着与旧块(最大size)相同的内容。函数返回指向新块的指针,新块可以与旧块的地址一样,因此,这时返回的指针可以与传入的指针一致。如果block是空指针,那么,realloc ()函数仅仅分配size字节的内存,并返回;如果size为零,那么,realloc ()函数就释放block所指向的内存。
free ()用来释放由动态分配函数分配的空间,其参数就是指向某空间的指针。注意,block必须是先前用动态分配函数(上述三个函数分配)所分配而取得的。如果传入无效指针,free ()函数可能摧毁内存管理机制,使得系统瘫痪。如果block为NULL,free ()函数不操作。
动态分配的数组(dynamically-allocated array)
注意区分,动态分配的数组和动态数组(dynamic array/growable array/ resizable array/dynamic table/array list);后者如C++语言的std::vector。
⑴、动态分配的一维数组
1 /* 动态分配的一维数组*/
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 int main()
7 {
8 char *s;
9 register int t;
10
11 s = malloc (80); /* 分配*/
12 if (!s) { /* 检查指针 */
13 printf ("内存分配失败");
14 exit (1);
15 }
16
17 get (s);
18 for (t=strlen (s)-1; t >= 0; putchar (s[t])); /* 反向打印 */
19
20 free (s); /* 释放 */
21 return 0;
22 }
⑵、动态分配的二维数组
1 /* 动态分配的二维数组*/
2 /* 一个表,计算~的~次幂*/
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 int pwr (int, int);
7
8 int main ()
9 {
10 /* 元素个数为的整数数组的指针*/
11 int (*iPtr)[10]; /* 这里的圆括号是必须*/
12 register int i, j;
13
14 iPtr = malloc (40 * sizeof(int)); /* sizeof确保可移植性*/
15 if (!iPtr) { /* 检查指针*/
16 printf ("内存分配失败");
17 exit (1);
18 }
19
20 for (j=1; j<11; j++)
21 for (i=1; i<5; i++) iPtr[i-1][j-1] = pwr (j, i);
22
23 for (j=1; j<11; j++) {
24 for (i=1; i<5; i++) printf ("%10d", iPtr[i-1][j-1]);
25 printf ("\n");
26 }
27
28 free (iPtr); /* 释放*/
29 return 0;
30 }
31
32 pwr (int a, int b)
33 {
34 register int t = 1;
35
36 for (; b; b--) t = t * a;
37
38 return t;
39 }
动态内存分配的常见错误
常见的动态分配内存的错误有:
⑴、内存分配函数返回的是空指针,没有检查就使用其返回的指针。应该在动态分配函数返回的同时对其返回值进行检查,以防止误用。
⑵、malloc ()函数返回的内存尚未初始化就引用它。
⑶、对所分配的内存进行的操作越过了边界。如数组操作时的下标“多1”或者“少1”。
⑷、忘记了在退出程序块时调用free()函数来释放内存,造成内存泄露。动态内分配存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同。
⑸、使用free()释放了内存后,没有将相应的指针设置为NULL,导致产生“野指针”(dangling pointer)。
⑹、调用free()函数释放了内存,却继续使用它。
⑺、调用free()函数释放了内存,后面再一次调用free()函数释放它。

1099

被折叠的 条评论
为什么被折叠?



