8.1.1 堆内存的申请分配
在堆中申请分配内存空间,有两个相关的库函数:malloc 和 calloc。
1.malloc 函数
malloc 函数的原型:
void *malloc(size_t size);
函数只有一个参数 size,它是 size_t 类型的,即无符号的整型数。函数返回值为 void 类型的指针。函数的功能就是在堆中申请参数 size 所指定字节数的一段内存空间,如果成功,则返回该段内存空间的首地址,即第一个字节所对应的内存地址;如果失败,则返回空指针。例如:
void *p = malloc(4);
定义 void 类型的指针变量 p,并通过 malloc 函数在堆中申请分配 4 字节的内存空间,并将返回值初始化给指针变量 p。如果申请分配成功,指针变量 p 的值即为所分配的内存空间首地址;如果申请分配失败,指针变量的值就为 NULL。
在堆中申请并分配了内存之后,就可以使用这块内存来存储数据了,例如在这 4 字节的内存空间中存储整数值 100:
if(p != NULL)
*(int*)p = 100;
先是通过 if 语句判断指针 p 是否为空指针,如果不是空指针,则通过指针 p 来访问在堆中所分配的 4 字节内存,并将其赋值为整数值 100。由于指针 p 是 void 类型的,因此需要先将它转换成 int 类型的指针,然后再通过解引用运算符来访问并进行赋值。
代码中是将堆中所申请分配的 4 字节内存视为整型变量的存储空间来使用。因此,可以在申请分配堆内存时,就对 malloc 函数所返回的指针进行转换。例如:
int *p = (int*)malloc(4);
将 malloc 所返回的 void 类型的指针,强制转换为 int 类型的指针,然后初始化给指针变量 p。
由于整型变量的存储空间大小并非固定,在不同的编译器和系统平台上可能会具有不同的值,因此,使用 sizeof 运算符来获取整型变量的存储空间大小,并根据该值来申请分配堆内存空间,是个更好的选择。例如:
int *p = (int*)malloc(sizeof(int));
通过 sizeof 运算符获取整型变量的存储空间大小,并根据该值来申请分配堆内存空间,将返回的内存地址初始化给指针变量 p。
下面访问堆中所申请分配的内存并对其进行赋值。
if(p != NULL)
*p = 100;
即将堆中所申请分配的内存空间,视为一个整型变量的内存空间,而指针 p 可视为指向该整型变量的指针。
也可以在堆中申请分配一个数组的内存空间。例如:
int *p = (int*)malloc(sizeof(int) * 5);
通过 malloc 函数在堆中申请分配一个大小为“sizeof(int) * 5”的内存空间,即可将所申请分配的内存空间视为一个长度为 5 的 int 类型数组的内存空间。并将返回值转换为 int 类型的指针初始化给指针变量 p,即指针 p 指向了堆中的长度为 5 的 int 类型数组的首地址。下面就通过该指针,利用循环来访问堆中数组的各元素并赋予新值。例如:

在 for 循环语句的循环体中,首先对指针 p 进行运算,依次产生指向数组各元素的指针,然后通过解引用访问各元素,并对其进行重新赋值。
也可以采用数组下标的形式来完成。例如:

同样地,也可以在堆中申请分配一个结构体大小的内存空间,并将该内存空间当作结构体变量一样来使用。例如,定义如下一个结构体:

定义了结构体 Stu,它有 3 个成员:name、age 和 score。并通过 typedef 给该结构体类型定义了别名 STU,因此,该结构体类型既可以使用“struct Stu”,也可以使用“STU”。
下面在堆中申请分配一个该结构体大小的内存空间:
STU *pstu = (STU*)malloc(sizeof(STU));
通过 sizeof 运算符获取结构体类型 STU 的大小,并根据该大小申请分配堆中的内存空间,并将该内存空间的首地址初始化给 STU 类型的结构体指针变量 pstu。可以将在堆中所申请分配的内存空间视为一个 STU 类型的结构体变量,而 pstu 是指向该结构体变量的指针。下面可以通过指针 pstu 来访问该结构体变量的各成员并进行赋值操作。例如:
strcpy(pstu->name, "zhangSan"); pstu->age = 22; pstu->score = 85.5f;
再通过指针 pstu 来访问并打印输出所有成员:
printf("Name:%s\n", pstu->name);
printf("Age:%d\n", pstu->age);
printf("Score:%.2f\n", pstu->score);
编译运行程序,结果如下:
Name:zhangSan Age:22 Score:85.50
2.calloc 函数
同 malloc 函数一样,calloc 函数也是用于在堆中申请分配内存空间,calloc 函数的原型为:
void* calloc(size_t num, size_t size);
该函数有两个参数,都是 size_t 类型。第一个参数 num 用于指定对象的数量,即 calloc 函数可以在堆中申请分配能存储指定数量对象的内存空间,第二个参数 size 用于指定对象的大小。因此,它非常方便为数组类型的对象开辟内存空间。例如:
int *p = (int*)calloc(5, sizeof(int));
该语句的功能为,通过 calloc 函数在堆中申请分配 5 个 int 类型大小的内存空间,即可视为一个长度为 5 的 int 类型数组的内存空间。函数返回的也是指向堆中所申请分配的内存首地址,为 void 类型的指针,因此,通过强制类型转换将其转换为 int 类型的指针初始化给指针变量 p。
另外,使用 calloc 函数还有一个特别之处,就是能够对堆中所申请分配的内存空间进行默认初始化,即将内存空间的各字节的都值初始化为 0,这是 malloc 函数所不具备的。例如:
int *p1 = (int*)malloc(sizeof(int));
int *p2 = (int*)calloc(1, sizeof(int));
printf("*p1 = %d\n", *p1);
printf("*p2 = %d\n", *p2);
定义了两个 int 类型的指针变量 p1 和 p2,然后分别通过 malloc 和 calloc 函数在堆中申请分配 int 类型大小的内存空间,并初始化给指针变量 p1 和 p2。最后,通过解引用运算符访问 p1 和 p2 所指向的内存空间数据,并通过 printf 函数打印输出。
编译运行程序,结果如下:
*p1 = 7219104 *p2 = 0
可见,指针 p1 所指向的内存空间是通过 malloc 函数申请分配的,它不会对内存空间数据进行初始化,因此,对应的内存空间的数据为一个随机值。而指针 p2 所指向的内存空间是通过 calloc 函数申请分配的,会对内存空间的数据进行初始化,因此,对应内存空间中数据的值为 0。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论