前言:
c提供了几个动态内存分配的函数,包含在 stdlib.h 头文件中:
函数原型如下:
void * malloc ( size_t size );
void free ( void *pointer );
malloc 的参数是所需分配内存的字节数byte,size_t 是无符号数(>=0),对于每个malloc返回的指针都要进行检查(是否为NULL)
对于有边界对齐要求的机器,malloc返回的内存起始位置始终能够满足对边界对齐要求最严格的类型的要求
void * calloc ( size_t num_elements,, size_t element_size );
void realloc ( void *ptr, size_t new_size );
malloc和calloc之间主要区别是:后者在返回指向内存的指针之前把它初始化为0。但如果程序只是想把一些值存储到数组中,这个初始化过程纯属浪费时间。
calloc和malloc之间另一个比较小的区别是:它们请求内存数量的方式不同。 calloc包括所需元素数量和每个元素的byte数。
使用了realloc之后,就不能再使用指向旧内存的指针,而是应该改用realloc所返回的新指针。
如果realloc函数的第一个参数是NULL,那么它的行为就和malloc一样了。
常见的动态内存错误:
写一个不易发生错误的内存分配器:
#include<stdlib.h>
#define malloc // do not invoke malloc directory
#define MALLOC(num,type) (type *)alloc( (num) * sizeof(type) )
extern void *alloc( size_t size );
#include<stdio.h>
#include<stdlib.h>
#include"alloc.h"
#undef malloc
//undo the malloc declaration before, so we could use malloc again
void *alloc( size_t num )
{
void *new_mem;
/*
* request the mem, test whether it it success
*/
new_mem = malloc( num );
if( new_mem == NULL ){
printf("out of memory\n");
exit(1);
}
return new_mem;
}
使用错误检查分配器 a_client.c
#include<stdio.h>
#include<stdlib.h>
#include"alloc.h"
int *function( size_t num )
{
int *new_mem;
/*
* acquire memory
*/
new_mem = MALLOC( num, int );
return new_mem;
}
int main( int argc, char *argv[] )
{
int *p = function( 20 );
for( int i = 0; i < 20; ++i, p++ ){
*p = i+1;
printf("the number is no:%d\n", *p);
}
exit( 0 );
}
内存分配实例:
补充一个知识,stdlib.h 自带的快速排序,qsort
void qsort{
void *base,
size_t num,
size_t width,
int (__cdecl *compare)( const void *, const void * )
};
int comp( const void *a, const void *b )
{
return *(int *)a - *(int *)b; //小到大排序,反过来就是大到小排序
}
int compare_integers( void const *a, void const *b )
{
register int const *pa = a;
register int const *pb = b;
return *pa > *pb ? 1 : *pa < *pb ? -1 : 0; // cool !
}
eg:排序一列整形
#include<stdio.h>
#include<stdlib.h>
/*
* qsort invoke this function
*/
int compare_integers( void const *a, void const *b )
{
register int const *pa = a;
register int const *pb = b;
return *pa > *pb ? 1 : *pa < *pb ? -1 : 0; // cool !
}
int main( int argc, char *argv[] )
{
int *array;
int n_values;
int i;
/*
* see how many values there
*/
printf( "How many values there?\n" );
if( scanf( "%d", &n_values) == EOF || n_values <= 0 ){
printf( "Illegal number of values.\n" );
exit( EXIT_FAILURE );
}
/*
* allocate mem to store the values
*/
array = malloc( n_values * sizeof( int ) );
if( array == NULL ){
printf( "can't get mem for that values!\n" );
exit( EXIT_FAILURE );
}
/*
* load these numbers
*/
for( i = 0; i < n_values; ++i ){
printf("? ");
if( scanf( "%d", array + i ) == EOF ){
printf( "error reading value #%d\n", i );
free( array );
exit( EXIT_FAILURE );
}
}
/*
* sort for these values
*/
qsort( array, n_values, sizeof( int ), compare_integers );
/*
* print the result
*/
printf( "\nThe result is as follows:\n" );
for( i = 0; i < n_values; ++i ){
printf( "%d\n", array[i] );
}
free( array );
exit( 0 );
}
eg:动态复制字符串(方便有效!)
#include<stdio.h>
#include<stdlib.h>
char * strdup( char const *string )
{
char *new_string;
new_string = malloc( strlen( string ) * sizeof( char ) + 1 );
if( new_string != NULL )
strcpy( new_string, string );
return new_string;
}