赞
踩
我们要想实现动态内存分配,就需要学习标准C提供的函数库:
#include <stdlib.h>
C库函数void *malloc(size_t size)
分配所需的内存空间,并返回一个指向它的指针。
函数名:malloc
形式参数:size_t size:内存块的大小,以字节为单位。本质上就是一个无符号的整型unsigned int
返回值类型:void*:该函数返回一个指针,指向已分配大小的内存,如果请求失败,返回NULL。
举例:
int *p = (int*)malloc(4);
说明:
#include <stdlib.h>
C库函数void * calloc(size_t nitems,size_t size)
分配所需的内存空间,并返回一个指向它的指针。 malloc和calloc之间不同的是,malloc不会设置内存为零,而calloc会设置内存为零。
void * calloc(size_t nitems,size_t size)
函数名:calloc
形式参数:
返回值类型:void*:该函数返回一个指针,指向已分配大小的内存。如果请求失败,返回NULL。
举例:
int *p = (int*)calloc(3,4); // p指向的空间大小是12个字节
if(!p)
{
printf("内存申请失败!\n");
}
printf("内存申请成功!\n");
说明:
calloc函数分配的内存有默认值,每个单元都是0;
calloc函数申请的内存空间连续;
calloc大多数为数组中的元素申请内存。
转存栈中数组中的数据;
int arr[3] = {10,20,30}; // 在栈区 int *p = (int*)calloc(3,4); // 申请内存,在堆区 if(!p) { puts("内存申请失败!\n"); } puts("内存申请成功!\n"); // 转存 for(int i = 0; i < 3; i++) { p[i] = arr[i]; } // 遍历 for(int i = 0; i < 3; i++) { printf("%d ",p[i]); } printf("\n"); // p使用完,记得释放内存 free(p); p = NULL; // 内存回收后,建议置空
#include <stdlib.h>
尝试重新调整之前调用malloc或calloc所分配的p所指向的内存块的大小。
void *realloc(void *ptr,size_t size)
函数名:realloc
形式参数:
返回值类型:void*:该函数返回一个指针,指向已分配大小的内存。如果请求失败,返回NULL。
案例:
int *p = (int*)malloc(4);
int *w = (int*)realloc(p,20);
// int *q = (int*)realloc(p,0); // 等效于free(p)
#include <stdlib.h>
释放之前调用malloc、calloc、realloc所分配的内存空间,访问完记得使用NULL置空。
void free(void *ptr)
函数名:free
形式参数:
返回值类型:void:没有返回值
注意:
说明:
void作为返回类型使用,表示没有返回值;作为形参表示形参列表为空,在调用函数时不能给实参
// 函数声明
void fun(void); // 等效于 void fun();
// 函数调用
fun();
void*是一个指针类型,但该指针的数据类型不明确,无法通过解引用获取内存中的数据,因为void*
不知道访问几个内存单元。
void*是一种数据类型,可以作为函数返回值类型,也可以作为形参类型。
void*类型的变量在使用之前必须强制类型转换,明确它能够访问几个字节的内存空间。
int *p = (int*)malloc(4);
double *p2 = (double*)malloc(8);
#include <stdio.h> #include <stdlib.h> // 函数定义 void* fun(void* p) // 指针函数(返回值类型是指针的函数,此时返回的是不明确类型,需要外部强转) { int *p; // double *p; // long *p; // char *p; return p; } // 函数调用 void mian() { int *p; void* a = fun(p); // 这种接收方式,实际上没有意义 printf("%p\n",a); // 可以正常打印,打印出一个地址 *a = 10; // 编译报错,void*变量不能解引用访问数据 int *w = (int*)a; *w = 10; // 编译和运行正常,void*变量a在使用前已经强制类型转换了,数据类型明确了,访问的内存单元明确了 }
说明:
char
,char*
,double*
等)的指针。char
,char*
,double*
等)的指针。总结:
void*
类型的变量解引用(因为不明确内存单元的大小)。我们对于内存的操作借助于stringh
这个库提供的内存操作函数。
#include <string.h>
填充s开始的堆内存空间前n个字节,使得每个字节值为c。
void *memset(void *s,int c,size_t n);
函数参数:
返回值:返回s
注意:c常常设置为0,用于动态内存初始化。
案例:
/** * 内存操作函数-memset */ #include <stdio.h> #include <stdlib.h> #include <string.h> void test1() { // 在堆内存申请了一块存储空间 int *p = (int*)malloc(4 * sizeof(int)); if(!p) { puts("内存分配失败!"); return;// 后续代码不需要执行 } // 给这块内存进行初始化操作(填充) memset(p,0, 4 * sizeof(int)); printf("%d\n",*(p+1)); // 内存使用完毕,进行回收 free(p); p = NULL; } int main() { test1(); return 0; }
#include <string.h>
拷贝src开始的堆内存空间前n个字节,到dest对应的内存中。
void *memcpy(void *dest,const void *src,size_t n);
适合目标地址与源地址内存无重叠的情况。
void *memmove(void *dest,const void *src,size_t n);
函数参数:
返回值:返回dest
注意:
案例:
/** * 内存操作函数-memcpy|memmove */ #include <stdio.h> #include <stdlib.h> #include <string.h> void test1() { // 申请内存 // int *p1 = (int*)malloc(4 * sizeof(int)); // int *p2 = (int*)malloc(6 * sizeof(int)); // 给p1,p2填充数据,可以使用for循环.. // for(int i = 0; i < 4; i++) // p1[i] = 10 + i; // memset(p2,0,6 * sizeof(int)); // 创建数组 int p1[4] = {11,12,13,14}; int p2[6] = {21,22,23,24,25,26}; // 将p1中的数据通过内存拷贝函数,拷贝到p2 // memcpy(p2+2,p1+1,2*sizeof(int)) // int p2[6] = {21,22,12,13,25,26} memmove(p2+2,p1+1,2*sizeof(int)); // 测试输出数组 for(int i = 0; i < 4; i++) { printf("%4d",p1[i]); } printf("\n"); for(int j = 0; j < 6; j++) { printf("%4d",p2[j]); } printf("\n"); // 如果使用手动分配的指针,一定要记得释放内存 // free(p1); // free(p2); // p1 = NULL; // p2 = NULL; } int main() { test1(); return 0; }
#include <string.h>
比较src和dest所代表的内存前n个字节的数据。
int memcmp(void *dest,const void *src,size_t n);
函数参数:
返回值:
0
:数据相同>0
:dest中的数据大于src<0
:dest中的数据小于src注意:n一般和src,dest的总容量一样;如果不一样,内存比较的结果就不确定 了。
案例:
/** * 内存操作-memcmp */ #include <stdio.h> #include <stdlib.h> #include <string.h> void test1() { // 申请内存 int *p1 = (int*)malloc(3*sizeof(int)); int *p2 = (int*)malloc(4*sizeof(int)); // int p1[4] = {1,0,3,6}; // int p2[4] = {1,2,3,4}; // int result = memcmp(p1,p2,4*sizeof(int)); *p1 = 65; *p2 = 70; char *a = (char*)p1;// 类型转换 char *b = (char*)p2; printf("%c,%c\n",*a,*b); int result = memcmp(a+1,b+1,1*sizeof(char)); printf("%d\n",result); } int main() { test1(); }
#include <string.h>
在s开始的堆内存空间前n个字节中查找字节数据c
int *memchr|*memrchr(const void *s,int c,size_t n);
函数参数:
返回值:返回查找到的字节数据地址
注意:如果内存中没有重复数据,memchr和memrchr结果一样;如果内存中有重复数据,memchr和memrchr结果不一样。
举例:
void *memrchr(..); // 在使用时编译会报错,需要使用外部声明
// 外部申请
extern void *memechr(..);
案例:
/** * 内存操作-memchr | memrchr */ #include <stdio.h> #include <stdlib.h> #include <string.h> // 声明外部函数 extern void *memrchr(const void *s,int c,size_t n); void test1() { // 申请内存 int *p = (int*)malloc(4*sizeof(int)); if(!p) { puts("内存分配失败!"); return; } // 给变量赋值 for(int i = 0; i < 4; i++) { p[i] = i * 2; } p[3] = 4; // 输出 for(int i = 0; i < 4; i++) { printf("%d,",p[i]); } printf("\n"); // 内存查找 memchr int *x = (int*)memchr(p,4,4*sizeof(int)); printf("%p--%p--%d\n",x,p,*x); // 内存查找 memrchr int *y = (int*)memrchr(p,4,4*sizeof(int)); printf("%p--%p--%d\n",y,p,*y); // 回收内存 free(p); p = NULL; } int main() { test1(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。