stdlib.h 中常用函数[1]内存分配和释放
基本信息:// joen.hong#gmain.com
// 可任意转载,但请注明连接;
// 本文为巩固基础学习之用;
// 2009年10月09日
// 本文内容来源于C库头文件和Linux manual:
// 可任意转载,但请注明连接;
// 本文为巩固基础学习之用;
// 2009年10月09日
// 本文内容来源于C库头文件和Linux manual:
在stdlib.h 中的几个重要内存管理函数为 calloc(), malloc(), free(), realloc();当然还有其他的函数,
这里不打算全部都列出来了。详细加深理解的话,还是要看手册和代码实现源文件。
这里不打算全部都列出来了。详细加深理解的话,还是要看手册和代码实现源文件。
一、内存分配和释放函数:
函数原型:void *calloc(size_t nmemb, size_t size);
功 能:calloc() 分配nmemb 个元素的数组空间,每个元素大小为size 个字节;返回分配内存的指针。
所分配的内存设置为0;如果nmemb 或size 为0,返回NULL或是一个可被成功传送给free函数的唯一指针值。
返 回 值:返回指向新分配内存指针,这个内存指针合适地对齐任何类型变量。出错返回NULL。
注意但nmemb 或size 为0时,成功也有可能返回NULL。
参考函数:sbrk(2);brk(2);mmap(2);alloca(3);
函数原型:void *malloc(size_t size);
功 能:malloc() 分配size 字节,返回指向分配到的内存的指针。内存不做清理。
如果size 为0,malloc() 返回NULL或是一个可被成功传送给free函数的唯一指针值。
返 回 值:返回指向新分配内存指针,这个内存指针合适地对齐任何类型变量。出错返回NULL。
函数原型:void free(void *ptr);
功 能:释放ptr 指向的内存空间,ptr 必须是由之前的malloc(),calloc(),或realloc()
调用返回的。否则,free(ptr) 之前已经被调用过,发生的行为是不确定的。
如果ptr 为NULL,就什么也不做。
返 回 值:没有返回值。
函数原型:void *realloc(void *ptr, size_t size);
功 能:realloc() 用来将ptr 指向的内存块的大小改为size 字节。The contents will be unchanged the minimum of
the old and new sizes;
新分配的内存不会被初始化。 如果ptr 为NULL,那么调用就等同于malloc(size),size 为任意合适值;
如果size 为0,并且ptr 又不是NULL,那么调用等同于 free(ptr)。除非ptr为空,否则ptr 必须是由之前的
malloc(),calloc(),或realloc()调用返回的。如果ptr指向区域已经被移除,那么会发生free(ptr) 效果。
返 回 值:realloc() 返回指向新分配的内存指针,这个内存指针合适地对齐任何类型变量,可能ptr 指向不同;
请求失败返回NULL。如果size 为0,返回NULL或是一个可被成功传送给free函数的唯一指针值。
如果realloc() 失败,ptr 指向的初始内存块,保持不变,不被释放或移动。
功 能:calloc() 分配nmemb 个元素的数组空间,每个元素大小为size 个字节;返回分配内存的指针。
所分配的内存设置为0;如果nmemb 或size 为0,返回NULL或是一个可被成功传送给free函数的唯一指针值。
返 回 值:返回指向新分配内存指针,这个内存指针合适地对齐任何类型变量。出错返回NULL。
注意但nmemb 或size 为0时,成功也有可能返回NULL。
参考函数:sbrk(2);brk(2);mmap(2);alloca(3);
函数原型:void *malloc(size_t size);
功 能:malloc() 分配size 字节,返回指向分配到的内存的指针。内存不做清理。
如果size 为0,malloc() 返回NULL或是一个可被成功传送给free函数的唯一指针值。
返 回 值:返回指向新分配内存指针,这个内存指针合适地对齐任何类型变量。出错返回NULL。
函数原型:void free(void *ptr);
功 能:释放ptr 指向的内存空间,ptr 必须是由之前的malloc(),calloc(),或realloc()
调用返回的。否则,free(ptr) 之前已经被调用过,发生的行为是不确定的。
如果ptr 为NULL,就什么也不做。
返 回 值:没有返回值。
函数原型:void *realloc(void *ptr, size_t size);
功 能:realloc() 用来将ptr 指向的内存块的大小改为size 字节。The contents will be unchanged the minimum of
the old and new sizes;
新分配的内存不会被初始化。 如果ptr 为NULL,那么调用就等同于malloc(size),size 为任意合适值;
如果size 为0,并且ptr 又不是NULL,那么调用等同于 free(ptr)。除非ptr为空,否则ptr 必须是由之前的
malloc(),calloc(),或realloc()调用返回的。如果ptr指向区域已经被移除,那么会发生free(ptr) 效果。
返 回 值:realloc() 返回指向新分配的内存指针,这个内存指针合适地对齐任何类型变量,可能ptr 指向不同;
请求失败返回NULL。如果size 为0,返回NULL或是一个可被成功传送给free函数的唯一指针值。
如果realloc() 失败,ptr 指向的初始内存块,保持不变,不被释放或移动。
二、函数基本应用:
1.二维动态数组分配练习:
1
#include
<
stdio.h
>
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int i, j, n, m;
7 scanf( " %d%d " , & n, & m);
8 int * array;
9 printf( " row: %d, col: %d\n " , n, m);
10
11 /* malloc 分配一维数组当二维数组使用
12 * ,引用方式:如下(1)(2)
13 */
14 array = ( int * )malloc(n * m * sizeof ( int ));
15 for (i = 0 ; i < n; i ++ )
16 for (j = 0 ; j < m; j ++ )
17 scanf( " %d " , array + m * i + j); /* (1) */
18
19
20 for (i = 0 ; i < n; i ++ ) {
21 for (j = 0 ; j < m; j ++ )
22 printf( " %d\t " , array[m * i + j]); /* (2) */
23 printf( " \n " );
24 }
25
26 free(array);
27 return 0 ;
28 }
29
$ cat testdata.txt
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int i, j, n, m;
7 scanf( " %d%d " , & n, & m);
8 int * array;
9 printf( " row: %d, col: %d\n " , n, m);
10
11 /* malloc 分配一维数组当二维数组使用
12 * ,引用方式:如下(1)(2)
13 */
14 array = ( int * )malloc(n * m * sizeof ( int ));
15 for (i = 0 ; i < n; i ++ )
16 for (j = 0 ; j < m; j ++ )
17 scanf( " %d " , array + m * i + j); /* (1) */
18
19
20 for (i = 0 ; i < n; i ++ ) {
21 for (j = 0 ; j < m; j ++ )
22 printf( " %d\t " , array[m * i + j]); /* (2) */
23 printf( " \n " );
24 }
25
26 free(array);
27 return 0 ;
28 }
29
5 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
$ ./a.out < testdata.txt
row: 5, col: 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1
#include
<
stdio.h
>
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int i, j, n, m;
7 scanf( " %d%d " , & n, & m);
8 printf( " row: %d, col: %d\n " , n, m);
9
10 /* 尝试类似一般二维数组引用的分配方法 */
11 int ** array;
12 array = ( int ** )malloc( sizeof ( int * ) * n);
13 for (i = 0 ; i < n; i ++ )
14 array[i] = ( int * )malloc( sizeof ( int ) * m);
15
16 for (i = 0 ; i < n; i ++ )
17 for (j = 0 ; j < m; j ++ )
18 scanf( " %d " , & array[i][j]);
19
20 for (i = 0 ; i < n; i ++ ) {
21 for (j = 0 ; j < m; j ++ )
22 printf( " %d\t " , array[i][j]);
23 printf( " \n " );
24 }
25
26 /* 释放内存比较麻烦, 注意顺序 */
27 for (i = 0 ; i < n; i ++ )
28 free(array[i]);
29 free(array);
30
31 return 0 ;
32 }
33
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int i, j, n, m;
7 scanf( " %d%d " , & n, & m);
8 printf( " row: %d, col: %d\n " , n, m);
9
10 /* 尝试类似一般二维数组引用的分配方法 */
11 int ** array;
12 array = ( int ** )malloc( sizeof ( int * ) * n);
13 for (i = 0 ; i < n; i ++ )
14 array[i] = ( int * )malloc( sizeof ( int ) * m);
15
16 for (i = 0 ; i < n; i ++ )
17 for (j = 0 ; j < m; j ++ )
18 scanf( " %d " , & array[i][j]);
19
20 for (i = 0 ; i < n; i ++ ) {
21 for (j = 0 ; j < m; j ++ )
22 printf( " %d\t " , array[i][j]);
23 printf( " \n " );
24 }
25
26 /* 释放内存比较麻烦, 注意顺序 */
27 for (i = 0 ; i < n; i ++ )
28 free(array[i]);
29 free(array);
30
31 return 0 ;
32 }
33
和引用和一般二维数组是一样的,只是二维数组在内存上是连续的。
而类似上面动态分配的二维数组,很可能在内存上并不连续,二进制代码中访问数据过程并不一样。
2.一种错误的应用方式:
1
#include
<
stdio.h
>
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int a = 5 , b = 10 ; /* 测试用 */
7 int i, j, n, m;
8 scanf( " %d%d " , & n, & m);
9
10 int ** array;
11 int * dest;
12 dest = ( int * )malloc( sizeof ( int * ) * n);
13 /* a,b,n,m,dest,array等的值可能已被修改,和变量在栈的分配顺序等有关 */
14 array = & dest; /* array必须是足够大的空间保存int*数组,但不是 */
15 for (i = 0 ; i < n; i ++ ) {
16 printf( " row: %d, col: %d\t " , n, m);
17 printf( " a: %d, b: %d\n " , a, b);
18 printf( " dest: 0x%x\t " , dest);
19 printf( " array: 0x%x\n\n " , array);
20
21 array[i] = dest + n * i;
22 }
23
24 for (i = 0 ; i < n; i ++ )
25 for (j = 0 ; j < m; j ++ )
26 scanf( " %d " , & array[i][j]);
27
28 for (i = 0 ; i < n; i ++ ) {
29 for (j = 0 ; j < m; j ++ )
30 printf( " %d\t " , array[i][j]);
31 printf( " \n " );
32 }
33
34 // free(dest);
35 return 0 ;
36 }
37
2 #include < stdlib.h >
3
4 int main( int argc, char * argv[])
5 {
6 int a = 5 , b = 10 ; /* 测试用 */
7 int i, j, n, m;
8 scanf( " %d%d " , & n, & m);
9
10 int ** array;
11 int * dest;
12 dest = ( int * )malloc( sizeof ( int * ) * n);
13 /* a,b,n,m,dest,array等的值可能已被修改,和变量在栈的分配顺序等有关 */
14 array = & dest; /* array必须是足够大的空间保存int*数组,但不是 */
15 for (i = 0 ; i < n; i ++ ) {
16 printf( " row: %d, col: %d\t " , n, m);
17 printf( " a: %d, b: %d\n " , a, b);
18 printf( " dest: 0x%x\t " , dest);
19 printf( " array: 0x%x\n\n " , array);
20
21 array[i] = dest + n * i;
22 }
23
24 for (i = 0 ; i < n; i ++ )
25 for (j = 0 ; j < m; j ++ )
26 scanf( " %d " , & array[i][j]);
27
28 for (i = 0 ; i < n; i ++ ) {
29 for (j = 0 ; j < m; j ++ )
30 printf( " %d\t " , array[i][j]);
31 printf( " \n " );
32 }
33
34 // free(dest);
35 return 0 ;
36 }
37