zoukankan      html  css  js  c++  java
  • C语言指针的那些坑

    那些年把我们坑惨的指针

    一、引言

      当我们使用c语言的时候,不可避免的就得用到指针,然后对于刚刚接触C语言的猿兄们,可能会有点不适应,特别是刚刚从python等离硬件很远的语言转过来的。

    下面我为大家总结下常见的几个坑。

    二、用事实说话

      

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define MAXLEN 100
     4 typedef struct
     5 {
     6     char* data;
     7     int len;
     8 }Node;
     9 
    10 void create(Node* head){
    11     Node* node = (Node*)malloc(sizeof(Node));
    12     node->data = (char*)malloc(MAXLEN*sizeof(char));
    13     head = node;
    14 }
    15 void destroy(Node* head){
    16     free(head->data);
    17     head->data = NULL;
    18     free(head);
    19 }
    20 int main(int argc, char const *argv[])
    21 {
    22     Node* p = NULL;
    23     create(p);
    24     printf("%p
    ", p);
    25     destroy(p);
    26     return 0;
    27 }

    哇!通过上面的代码,我们看到我们可以很容易的通过create创建一个Node结点,下面我们就来理性分析一波。

    首先,malloc在堆空间申请空间,create运行结束后,堆空间内存也不会释放,对吧?很有道理,然后我们再把开辟的空间的地址给head返回

    正如我们知道的我们传进去的是指针(是一个地址)按理来说返回的应该是新申请的堆空间地址。

    然而,并不是,我们看看结果:

    返回的是一个NULL,再destroy一次(free了NULL)

    就出现 seg fault.

    惊不惊喜,意不意外!!!黑人问号.jpg

    那问题在哪里??? why??? why???

    下面我们来看看问题出在哪里。

    三、问题分析

      在c语言中,我们将char*,int*等带有*的类型称为指针类型,指针类型同int,char,float,double一样都是基本数据类型。

    int保存的32位整型。.eg. int sum = 10。sum实际上是一个内存地址,这个内存地址的值就是10。而指针类型int* p = &sum

    p实际上也是个内存地址,而其值就是&sum(sum的内存地址)。

    在分析之前我们先来认识几个符号:

    *:取值符号,取对应内存的值,此外也是指针的标识符

    ->:取值符号,取对应内存的值

    &:取地址符号,取变量名对应的地址

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    在我们的问题中我们将一个Node 类型指针传入create,实际就是将实参 Node* p,复制给形参Node* head.

    这里复制的是"p"也就是指针保存的地址。head这个指针现在保存的地址就是p指向的地址了。

    然后我们malloc一快堆区空间,返回一个堆区内存地址给head,也就是说:

    之前head指针保存的地址是实参p的地址,而现在head指向的地址是,堆区内存的地址。

    哈哈,原来问题就出在这里。我们以为传就去p的地址,然后可以通过12-13这两个语句,让p保存

    堆区内存地址,然后并不是这样。那我们可以怎样解决了?

    很容易*这个符号就是取内存对应的值,也就是说我们只要*head这样就是指向p指向内存的值,我们再

    把malloc申请的地址的值给*head,这样就成功解决了。话不多说上code

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXLEN 100
    typedef struct 
    {
        char* data;
        int len;
    }Node;
    
    void create(Node* head){
        Node* node = (Node*)malloc(sizeof(Node));
        node->data = (char*)malloc(MAXLEN*sizeof(char));
        *head = *node;
        free(node);
    }
    void destroy(Node* head){
        free(head->data);
        head->data = NULL;
        free(head);
    }
    int main(int argc, char const *argv[])
    {
        Node* p = (Node*)malloc(sizeof(Node));
        create(p);
        printf("%p
    ", p);
        destroy(p);
        return 0;
    }

    此外还可以直接返回malloc申请到的地址。

    转载请注明出处:https://www.cnlogs.com/jake9402

  • 相关阅读:
    git线上操作
    IDEA快捷方式
    Java 四种线程池
    java 获取当前天之后或之前7天日期
    如何理解AWS 网络,如何创建一个多层安全网络架构
    申请 Let's Encrypt 通配符 HTTPS 证书
    GCE 部署 ELK 7.1可视化分析 nginx
    使用 bash 脚本把 AWS EC2 数据备份到 S3
    使用 bash 脚本把 GCE 的数据备份到 GCS
    nginx 配置 https 并强制跳转(lnmp一键安装包)
  • 原文地址:https://www.cnblogs.com/jake9402/p/7712180.html
Copyright © 2011-2022 走看看