C 语言几个内存管理函数整理
对于常用C/C++语言的人来说,内存管理无疑是十分重要的一个工作,因此经常会用到一些内存管理函数,在这里做一个简单的整理。
mallco
void *malloc(unsigned int num_bytes);
动态内存分配,用于申请一块连续的指定大小的内存块区域以 void*
类型返回分配的内存区域地址,即再分配内存之后,该指针已经保存了一个地址。
void*
类型表示未确定类型的指针,一般需要强制转换为需要的指针类型。
realloc
void *realloc(void *mem_address, unsigned int newsize);
先判断当前的指针是否有足够的连续空间,如果有,扩大 mem_address
指向的地址,并且将mem_address
返回,如果空间不够,先按照 newsize
指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来 mem_address
所指内存区域(注意:原来指针是自动释放,不需要使用 free
),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
free
void free(void *ptr);
释放 malloc
(或 calloc
、realloc
)函数给指针变量分配的内存空间的函数.
注意:在 free
指针 ptr
指向的内存之后,为了避免之后重新用 free
错误释放这块儿已经释放的内存,一般需要将 ptr=NULL
。
memset
void *memset(void *s, int ch, size_t n);
将 s
中当前位置后面的 n 个字节 (typedef unsigned int size_t
)用 ch
替换并返回 s 。
作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
memcpy
void *memcpy(void *dest, const void *src, size_t n);
从源 src
所指的内存地址的起始位置开始拷贝 n 个字节到目标 dest
所指的内存地址的起始位置中。
这里需要对 memcpy
这个函数做一些说明,memcpy
函数后经常还会有一个 malloc
函数,那么这里就有一个疑问,为什么用memcpy函数拷贝了一份内存之后还要使用 malloc
函数,下面我们就来学习一下。
下面是一个代码片段:
// 定义一个结构体
typedef struct _Test_Data{
int width;
int height;
int* pMyData[2];
}TESTDATA, *PTESTDATA;
//主函数
int main(){
int data[] = {1, 2, 3, 4, 5};
TESTDATA sData1 = {0};
sData1.width = 5;
sData1.height = 3;
sData1.pMyData[0] = data;
sData1.pMyData[1] = data + 2;
TESTDATA sData2 = { 0 };
memcpy(&sData2, &sData1, sizeof(TESTDATA));
cout << "sData1 address " << &sData1 << endl << "sData2 address " << &sData2 << endl << endl;
cout << "sData1.width " << sData1.width << endl << "sData2.width " << sData2.width << endl << endl;
cout << "sData1.height " << sData1.height << endl << "sData2.height " << sData2.height << endl << endl;
cout << "sData1.pMyData[0] address " << sData1.pMyData[0] << endl << "sData2.pMyData[0] address " << sData2.pMyData[0] << endl << endl;
cout << "sData1.pMyData[1] address " << sData1.pMyData[1] << endl << "sData2.pMyData[1] address " << sData2.pMyData[1] << endl << endl;
*(sData2.pMyData[0] + 1) = 15;
cout << "*(sData1.pMyData[0]+1) " << *(sData1.pMyData[0] + 1)<< endl;
cout << "*(sData2.pMyData[0]+1) " << *(sData2.pMyData[0] + 1)<< endl <<endl;
sData2.pMyData[0] = (int*)malloc(5 * sizeof(int));
memcpy(sData2.pMyData[0], sData1.pMyData[0], 5 * sizeof(int));
*(sData2.pMyData[0] + 1) = 9;
cout << "*(sData1.pMyData[0]+1) " << *(sData1.pMyData[0] + 1) << endl;
cout << "*(sData2.pMyData[0]+1) " << *(sData2.pMyData[0] + 1) << endl;
return 0;
}
以上代码中,我们先定义了一个结构体变量 sData1
,然后使用 memcpy
函数拷贝一份内存到 sData2
变量的首地址处,此时地址模型如下:
即此时两个结构体变量的在内存中的地址虽然不一样,但是结构体变量中的成员具有相同的值,这包括,变量 width
,height
,以及 pMyData
数组中存放的地址,结果如下:
由于 sData1
和 sData2
中的变量共用一块内存,因此改变一个结构体的成员变量时,另一个结构体成员变量的值也会随着改变;
上面代码中设置 *(sData2.pMyData[0] + 1) = 15
; 此时,*(sData1.pMyData[0] + 1)
的值也为15,结果如下:
因为 memcpy
函数使得 sData1.pMyData[0]
和 sData2.pMyData[0]
指向同一块内存,因此修改其中给一个的值自然会使得另外一个的值发生改变。因此,在使用 memcpy
拷贝结构体变量时一定要注意,若结构体中有指针成员变量,则应当在 copy
之后为结构体中的指针变量分配内存,然后再使用一次 memcpy
来拷贝内存。
memmove
void *memmove( void* dest, const void* src, size_t count );
由 src
所指内存区域复制 count
个字节到 dest
所指内存区域。