C语言指针易犯错误

1. 指针作为函数参数进行传递

下面的代码本意是想在main中定义一个指针p,然后将其传给func_memory()函数,让func_memory函数申请一块内存,然后在main函数中对这块内存进行拷贝操作。

如下的代码运行会产生“segment Fault”,程序直接崩溃。

int main(void)
{
    char *str = "hello world";
    char *p = NULL;
    func_memory(p, strlen(str)+1);
    memcpy(p, str, strlen(str));
    printf("p_data=%s", p);
    if (p){
        free(p);
    }
    return 0 ;
}

void func_memory(void *p1, int len)
{
    p1 = malloc(len);
    if (NULL != p1){
        memset(p1, 0 , len);
    }
}

原因分析:main中在调用func_memory()的时候,是将实参p的值传递给了形参p1,是值传递,即p1=p=NULL。而这个传递是单向的,p和p1位于两个独立的栈帧上,对p1赋值,不会修改p。除将p的值传递给p1外,二者没有任何关系。所以,在func_memory()中,p1指向了malloc的内存,而调用函数中的p还是NULL,没有指向任何有效的内存。所以对p的操作会引起 "segment Fault"。

解决办法:

方法一:传递地址

在调用函数中将指针的地址传递给被调函数,在被调函数中通过指针的地址对指针进行赋值。

int main(void)
{
    char *str = "hello world";
    char *p = NULL;
    func_memory(&p, strlen(str)+1);
    memcpy(p, str, strlen(str));
    printf("p_data=%s", p);
    if (p){
        free(p);
    }
    return 0 ;
}

void func_memory(void **p1, int len)
{
    *p1 = malloc(len);
    memset(*p1, 0 , len);
}

代码分析

char *p=NULL;编译器对于这条语句的理解是:分配一块内存,这块内存的名字是p,内存中存放的是一个指向char型数据的地址,但是这个地址目前是NULL,也就是没有存放任何char型数据的地址。

在调用函数func_memory时,相当于 "void **p1 = &p;",  p1的值为p的地址,也就是说p1这个变量中存放的是p的地址(假设p的内存地址为 "0x1000", 这个地址上的值为NULL,变量p1的地址为 "0x1004",这块地址上存储的值为0x1000。)。"*p1" 表示为p1所指的内存进行赋值操作,也就是为0x1000这个内存进行赋值操作,就是将malloc内存的地址值赋给了p,也就是说:p指向了这块内存。

知识点说明:p为指针,那么 *p = xxx,就表示为p所指向的内存赋值为xxx,p所指向的内存就是指针变量p中存放的那个内存。

int a = 10;
int *p = &a;
*p = 100;         //*p = p = 100

char *p = NULL;
char **p1 = &p;
*p1 = 0x1004;    //*p1 = p = 0x1004

方法一:将malloc的地址返回

要知道malloc的内存存在于堆上,除非手动释放或者程序退出,否则是会一直存在的。所以我们可以将malloc的内存地址返回给被调用函数。

int main(void)
{
    char *str = "hello world";
    char *p = NULL;
    p = (char *)func_memory(strlen(str)+1);
    if (NULL != p){
        memcpy(p, str, strlen(str));
        printf("p_data=%s", p);
        free(p);
    }
    return 0 ;
}

void *func_memory(int len)
{
    void *p1 = NULL;
    p1 = malloc(len);
    if (NULL != p1){
        memset(*p1, 0 , len);
    }
    return p1;
}

注意点:对于上面的malloc和free分别在两个不同的函数的场景中,一定不要忘记free。

 2. 对指针sizeof

sizeof(p):sizeof 是c语言的关键字(sizeof加括号,完全是为了使括号内的内容成为一个整体),对一个指针执行sizeof操作,计算的是指针的长度(指针的长度与平台和编译器有关,通常32位系统为4字节,64位系统为8字节),而不是指针指向内容的长度。

char *p = NULL;
p = (char *)malloc(sizeof(char)*15);
memset(p, 0, sizeof(char)*15);

sizeof(p);   //32位系统下,gcc编译器下值为4,虽然p指向15个字节的空间

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值