c语言中malloc函数的一个陷阱(二级指针的使用)

前段时间,学生在使用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函数可以模拟动态数组。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值