前段时间,学生在使用malloc分配int型数组空间的过程中,遇到了一点问题。
一、正确的malloc使用
看下面的程序:
/* malloc_right.c */
#include <stdio.h>
#include <malloc.h>
int * init_int_arr()
{
int * temp_arr = (int *)malloc(4 * sizeof(int));
for(int i = 0; i < 4; i++) {
*(temp_arr + i) = i * 2;
}
return temp_arr;
}
int main(void)
{
int * int_arr;
int_arr = init_int_arr();
for(int i = 0; i < 4; i++){
printf("[%d]: %d\n", i, int_arr[i]);
}
return 0;
}
编译,运行:
看到,编译过程中,没有错误,而且得到了预期的结果。这种用法是正确的。
二、错误的malloc使用
看下面程序:
/* malloc_error.c */
#include <stdio.h>
#include <malloc.h>
void init_int_arr(int * temp_arr)
{
temp_arr = (int *)malloc(4 * sizeof(int));
for(int i = 0; i < 4; i++) {
*(temp_arr + i) = i * 2;
}
}
int main(void)
{
int * int_arr;
init_int_arr(int_arr);
for(int i = 0; i < 4; i++){
printf("[%d]: %d\n", i, int_arr[i]);
}
return 0;
}
编译,运行如下:
看到,编译过程没有报错,但是运行时得到了不可知的结果。我们对这个程序进行一下测试。看下面程序:
/* test_malloc_error.c */
#include <stdio.h>
#include <malloc.h>
void init_int_arr(int * temp_arr)
{
temp_arr = (int *)malloc(4 * sizeof(int));
printf("in malloc int_arr address: %p\n", temp_arr);
for(int i = 0; i < 4; i++) {
*(temp_arr + i) = i * 2;
}
}
int main(void)
{
int * int_arr;
printf("before malloc int_arr address: %p\n", int_arr);
init_int_arr(int_arr);
printf("after malloc int_arr address: %p\n", int_arr);
return 0;
}
编译,运行后为:
可以看到,在对int_arr分配空间前,其地址为:0000000000000010,在初始化函数init_int_arr()中进行空间分配时,操作的地址为:0000000000787510,但是当从init_int_arr()跳出后这个地址并没有被返回给int_arr变量。
这实际是指针运用的一个陷阱,只需要记住一条,指针也是变量。
这有点类似于如下的程序:
/* change_int.c */
#include <stdio.h>
void change_int(int t)
{
t = 5;
}
int main(void)
{
int a = 3;
printf("before change a = %d\n", a);
change_int(a);
printf("after change a = %d\n", a);
return 0;
}
这种方式不会使a的值发生改变。
三、二级指针的使用
那可不可以不使用返回值的方式,对int数组进行空间分配呢,可以,采用二级指针。
如下程序:
/* malloc_pp.c */
#include <stdio.h>
#include <malloc.h>
void init_int_arr(int** temp_arr)
{
*temp_arr = (int *)malloc(4 * sizeof(int));
for(int i = 0; i < 4; i++) {
*(*temp_arr + i) = i * 2;
}
}
int main(void)
{
int** int_arr;
init_int_arr(int_arr);
/*------------------------- print -------------------------*/
for(int i = 0; i < 4; i++){
printf("[%d]: %d\n", i, (*int_arr)[i]);
}
return 0;
}
编译,运行如下:
这里采用二级指针的方式,便可以将int_arr在函数中直接初始化了。
四、模拟动态数组
这种方式配合realloc函数可以模拟动态数组。如下程序:
/* relloc_pp.c */
#include <stdio.h>
#include <stdlib.h>
void init_int_arr(int** temp_arr, int size)
{
*temp_arr = (int *)malloc(size * sizeof(int));
}
void update_int_arr(int ** temp_arr, int size)
{
*temp_arr = (int *)realloc(* temp_arr, size * sizeof(int));
}
int main(void)
{
int ** p_int_arr;
int *int_arr;
p_int_arr = &int_arr;
init_int_arr(p_int_arr, 4);
int_arr[0] = 2;
int_arr[1] = 4;
int_arr[2] = 6;
int_arr[3] = 8;
for(int i = 0; i < 4; i++){
printf("[%d]: %d\n", i, int_arr[i]);
}
printf("---------------- update --------------------\n");
update_int_arr(p_int_arr, 8);
int_arr[0] = 12;
int_arr[1] = 14;
int_arr[2] = 16;
int_arr[3] = 18;
int_arr[4] = 20;
int_arr[5] = 40;
int_arr[6] = 60;
int_arr[7] = 80;
for(int i = 0; i < 8; i++){
printf("[%d]: %d\n", i, int_arr[i]);
}
return 0;
}
编译,运行如下:
数组长度发生了变化。
五、结论
1、使用malloc分配空间时,要使用返回空间首地址形式;
2、如果在初始化函数中以参数传递形式分配空间,可以使用二级指针;
3、利用二级指针配合realloc函数可以模拟动态数组。