zoukankan      html  css  js  c++  java
  • c指针参数常见错误

    参数的地址是可以修改的,修改后的地址是不可能传回给调用处的指针变量。也就是说,可以修改参数地址所指的单元的值,这是可以传回到调用处的变量里面的。
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int subFunc(int arr[3]);
    
    //交换两整数
    void change(int *data1, int *data2) {
        int *temp;
    
        //交换两数的地址
        temp = data1;
        data1 = data2;    //修改参数1的地址
        data2 = temp;     //修改参数2的地址
    
        //交换后的地址在函数内没问题,但不能传回主程序
        printf("change:data1=%d, data2=%d
    ", *data1, *data2);
    
        return ;
    }
    
    //动态获得内存                             //|  //改为如下内容便可以传回主程序
    void getMemory(int size, char *str) {      //|  char *getMemory(int size) {
        //动态分配的内存地址赋给str            //|
        str = (char *)malloc(size);            //|      return (char *)malloc(size);
                                               //|
        return ;                               //|  }
    }                                          //|
                                               //|  //主程序的调用也得改成: p = getMemory(40) ;
    int main(void)
    {
        int x = 25, y = 87 ;
    
        change(&x, &y);
        printf("main:x=%d, y=%d
    ", x, y);    //x,y未得到交换
    
        getMemory(40, p);    //p未得到内存
        strcpy(p, "这是小雅的C语言教程");    //这句有错,注释之后才能得到上图结果
        free(p) ;
    
        return 0;
    }
    
    二、用局部变量的地址作返回值
    这是初学者常犯的错误。小雅在开始做这个例子时,没有用数组,而是用整型变量,结果令我大吃一惊,不管怎么试,结果全是正确的。可小雅明明知道这程序是有毛病的,为什么不出错呢?任何事都经不起琢磨,终于明白了其中的原因,但在这儿不能说,不是小雅卖关子,是因为说了反让初学者糊涂。
    
    #include <stdio.h>
    
    int *setData(void) {
        int arr[3] ;  //|   static int arr[3] ;
    
        arr[0] = 10 ;
        arr[1] = 35 ;
        arr[2] = 48 ;
    
        return arr ;  //局部变量随函数结束而消亡,因此,返回之后是不正确的
    }
    
    int main(void)
    {
        int i ;
        int *rst ;
    
        rst = setData();
        for (i=0; i<3; i++) {
            printf("%3d
    ", rst[i]);
        }
    
        return 0;
    }
    上面的错误是将消亡的地址返回,修正的方法可以考虑2种,一是将函数中的数组改为静态的。另一种办法是再动态申请内存。这样修改之后固然正确,但如果主程序中的rst改为数组,结果又怎样呢?这将导致编译错误。因为数组的地址不能被修改。
    三、双重指针作参数
    上面第一个例子讲到,不能把指针的地址传给调用处的变量,但实际编程时的确有这种需求,希望调用一个函数,使得原来的空指针变成有数据内容的指针。
    这其实不难实现,大家只要比较一下以前讲到的基本类型(譬如int)作参数时,不能通过参数返回内容,我们就改成“int *”这样的指针类型作参数,从而解决这个问题。现在我们只要用双重指针便同样可以解决指针的地址传送的问题。但要注意:“int *”作参数,调用时用“&变量”;“int **”作参数,调用时用“&指针变量”。
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void setData(int **ptr) {
        int *p = (int *)malloc(3 * sizeof(int));
    
        p[0] = 10, p[1] = 35, p[2] = 48 ;
        *ptr = p;  //注意:是将申请的内存地址赋给*ptr
    
        return ;
    }
    
    int main(void)
    {
        int i ;
        int *data = NULL ;
    
        //这句有错,应该用指针变量data的地址作参数
        setData(data);  //|   setData(&data);
    
        for (i=0; i<3; i++) {
            printf("%3d
    ", data[i]);
        }
    
        return 0;
    }
    
  • 相关阅读:
    Mac如何自定义本地化文件夹名
    Mac如何升级自带的vim
    0. GC 前置知识
    Git如何修改一个过去的Commit
    1. GC标记-清除算法(Mark Sweep GC)
    防火墙、WAF、IPS、IDS都是什么
    Python dir和vars的区别
    【Kafka】Kafka数据可靠性深度解读
    Java网络编程基础之TCP粘包拆包
    【Kafka】Consumer配置
  • 原文地址:https://www.cnblogs.com/457220157-FTD/p/5454138.html
Copyright © 2011-2022 走看看