zoukankan      html  css  js  c++  java
  • 指针做形参做局部变量以及内存分配

    一级指针做形参:首先一定要明白形参和你传递参数的那个实参是两个不同的变量,即使同名也还依然不同。指针传递的是一个变量或者一个值的地址,但是它本身还是采用值传递的方式。即你不能使它指向另外一块地址,但是你可以改变它指向的空间里存的值。

    二级指针做形参:二级指针也是传值,但是他指向的地址是个一维指针,所以可以改变二维指针指向的地址空间里的内容也就是要申请空间的一维指针,不能改变二维指针本身的值,即不能让他指向一个新的一维指针。所以二维指针传递的是一个一维指针。

    具体看下面这个程序以及输出:

    #include<stdio.h>
    #include <malloc.h>
    #include <string.h>

    void GetMemory1(char *p)
    {
    //该函数的形参为字符指针,在函数内部修改形参并不能真正改变传入形参的实参值。
    //因此在主函数中执行完下面两句之后
    //char *str1 = NULL;
    //GetMemory1(str1);
    //str1仍然为NULL,因此会报内存错误,没有输出结果。
    p = (char *)malloc(100);

    //要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
    if (p == NULL)
    {
    printf("error memory");
    }
    }
    /*但是上面的函数参数变为*char *&p就可以在主函数中正常输出了。
    指针做形参也是采用值传递的方式,也就是会把指针的值-地址传过去,所以可以改变这个地址里的内容,
    但是你不能改变指针的值,也就是指向的地址。但是引用就是变量的别名,所以可以改变指针的值,
    所以就可以在函数里申请空间
    */

    char *GetMemory2(void)
    {
    char p[] = "hello world";
    return p; //p[]数组为函数内部局部变量,在函数返回后,内存已经被释放了,
    //所以在主函数中调用该函数str2 = GetMemory2();输出的可能为乱码
    }

    void GetMemory3(char **p,int num)
    {
    *p = (char *)malloc(num);

    //要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
    if (*p == NULL)
    {
    printf("error memory");
    }
    }
    void main()
    {
    int n=0;
    char *str1 = NULL;
    char *str2 = NULL;
    char *str3 = NULL;

    //GetMemory1(str1);
    //strcpy(str1,"Hello world");
    //printf("%s\n",str1);

    str2 = GetMemory2();
    printf("%s\n",str2);//输出乱码

    GetMemory3(&str3,100);
    strcpy(str3,"hello world");
    printf("%s\n",str3);//输出hello world

    char *str4 = (char *)malloc(100);
    if (str4 == NULL)
    {
    printf("error memory");
    }
    else
    {
    strcpy(str4,"Hello");
    free(str4);
    str4 == NULL;//free后要置空,否则str可能变成“野指针”
    }
    if (str4 != NULL)
    {
    strcpy(str4,"world");
    printf("%s\n",str4);//输出world
    }
    scanf("%d",&n);
    }

    指针做局部变量:如果你申请了空间(用new等,赋值不算)又没有delete,那么这个空间在你程序运行结束之前不会释放,只要你知道这个空间的地址,就可以访问。这里的赋值不算是指,比如,你先定义一个数组,然后把数组名赋值指针。但是char *d = "ZET";这种形式相当于new了4个空间。

    下面是中兴通讯2012校招笔试题目,问输出什么?

    当时答错(狂汗),现在搞明白,在函数里写了注释:

    #include <stdio.h>

    //此函数中d也是个局部变量,函数执行完自动销毁,但是指针分配的空间不会被自动回收,除非程序员delete掉。
    //所以这个可以正常输出。
    char *a()
    {
    char *d = "ZET";//这个初始化的一种形式,相当于分配了四个空间
    return d;
    }

    //但是第二个数组空间是系统维护的,函数执行完自动销毁
    char *b()
    {
    char p[10] = {"3G平台"};
    return p;
    }


    //参数是值传递方式,改变形参的地址,传递的实参的地址确不会因此改变
    void c(int n,char *pName)
    {
    char *a[4] = {"aaa","bbb","ccc","ddd"};
    pName = a[n];
    }

    void main()
    {
    int n=0;
    char *pName = "DB";
    printf("%s\n",a());//输出ZET
    printf("%s\n",b());//随机输出乱码

    c(2,pName);
    printf("%s\n",pName); //输出DB,因为char *pName = "DB";已经使得pName指向了DB,但c(2,pName);并不能改变pName指向的地址。
    //形象点说就是:我有一个箱子给你用,你可以在里面装东西,但是你不能把我的箱子换成另外一个给我。
    //在这里指的是不能函数调用不能使pName变成函数中的二维数组a。

    scanf("%d",&n);
    }

    指针做形参,指针做局部变量,数组做形参,数组做局部变量之类的题目非常容易考到,而且容易迷糊,得不断学习...

  • 相关阅读:
    从1.5k到18k, 一个程序员的5年成长之路
    我是如何准备技术面试的
    10个惊艳的Ruby单行代码
    经典Spring面试题和答案
    数据分析应该要避免的6个错误
    代码重构的实战经验和那些坑
    勾勒物联网与大数据的数据中心路线图
    共筑Spark大数据引擎的七大工具
    es6学习总结(一)
    vue-cli搭建与vue-router(路由配置)
  • 原文地址:https://www.cnblogs.com/stoneJin/p/2183962.html
Copyright © 2011-2022 走看看