精华内容
下载资源
问答
  • 一、指针值传递 <span style="color:rgba(0, 0, 0, 0.75)"><span style="color:#000000"><code>//test.c #include <cstdio> #include <cstring> #include <cassert> void ...

    一、指针的值传递

    <span style="color:rgba(0, 0, 0, 0.75)"><span style="color:#000000"><code>//test.c
    #include <cstdio>
    #include <cstring>
    #include <cassert>
    
    void fun(char* p){
        p = (char*)malloc(sizeof(char));
        assert(p!=NULL);
        strcpy(p,"hello");
        //free(p)
    }
    
    int main(void){
        char* p = NULL;
        fun(p);
        printf("p=%s\n",p);
    }</code></span></span>

    这里写图片描述

    执行结果中并未输出字符串hello其实这里主函数调用fun函数,形参向实参传递参数的时候,发生的是拷贝。在fun函数中对局部指针变量p的任何修改都不会影响到主函数中的指针变量p。 
    下面简单的用函数栈帧空间图分析一下: 
    这里写图片描述

    值传递,形参的修改不会影响到实参

    二、指针的地址传递 
    由于实参是一个一级指针的地址,要传入这样的地址给形参,这需要一个对应类型的二级指针来接受一级指针的地址。

    <span style="color:rgba(0, 0, 0, 0.75)"><span style="color:#000000"><code>//test.c
    #include <cstdio>
    #include <cstring>
    #include <cassert>
    void fun(char** p){
        *p = (char*)malloc(sizeof(char)*100);
        assert(*p != NULL);
        strcpy(*p,"hello");
    }
    
    int main(void){
        char* p = NULL;
        fun(&p);
        printf("p=%s\n",p);
        free(p); 
        return 0;
    }</code></span></span>

    上述代码的执行结果是:p=hello 
    这里写图片描述

    指针的地址传递经常用在没有头节点的链表中,因为在创建和销毁链表时,头指针的值需要被修改。如果用一级指针接收发生的是值传递,要修改其值必须用二级指针接收一级指针的地址,在这个地址对应的内存块进行修改。

    三、指针的引用传递 
    用二级指针操作一级指针的内存往往让人难以理解,甚至往往还会发生内存泄漏的风险,在C++中,可以通过指针的引用简化这样的内存模型,实际上在编译器内部还是处理为二级指针,当使用时,解引用为一级指针,如对无头结点链表的初始化、销毁等操作,也可以使用一级指针的引用简化问题的处理。

    <span style="color:rgba(0, 0, 0, 0.75)"><span style="color:#000000"><code>//test.cpp
    #include <iostream>
    using namespace std;
    
    void fun(char* &p){
        p = new char[100];
        strcpy(p,"hello");
    }
    
    int main(){
        char* p=NULL;
        fun(p);
        cout<<"p = "<<p<<endl;
        delete [] p;
        return 0;
    }</code></span></span>

    这里写图片描述
    怎么理解一级指针的引用传递呢,编译器在内存中开辟了临时量,用于存储引用变量的地址,一但使用引用变量就进行解引用。所以在外部看来,似乎就是使用了原变量,有兴趣的同学可以反汇编源代码。从汇编的角度去理解引用,看看底层语言是怎么处理引用的,相信会对引用有更深刻的理解。 
    这里写图片描述

    展开全文
  • 1.普通传递 void f( int p){ printf("\n%x",&p); printf("\n%x",p); p=0xff; } void main() { int a=0x10; printf("\n%x",&a); printf("\n%x\n",a); f(a); printf("\n%x\n",a);...2.引用传递 void f

    1.值传递

    void f( int  p){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	p=0xff;
    }
    void main()
    {
    	int a=0x10;
    	printf("\n%x",&a);
    	printf("\n%x\n",a);
    	f(a);
    	printf("\n%x\n",a);
    }
    


    通过上例我们可以看到,int a=0x10,存放的地址为0x12ff44,值为10,当调用f(a)时,传递给p的值为10,但是p的地址为0x12fef4,当改变p=0xff,时是改变地址为0x12fef4中的内容,并没有改变0x12ff44中的内容,所以调用f(a),后a的值仍然为0x10,所以值传递无法改变变量的值。示意图如下:


    2.引用传递

    void f( int & p){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	p=0xff;
    }
    void main()
    {
    	int a=0x10;
    	printf("\n%x",&a);
    	printf("\n%x\n",a);
    	f(a);
    	printf("\n%x\n",a);
    }
    

    通过上面引用传递传递案例我们可以看到,调用f(a)时,传递给p的是a的地址,所以p和a的地址都是0X12ff44,所以p就是a,改变p当然能改变a。示意图如下:

    3.指针传递

    void f( int*p){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	printf("\n%x\n",*p);
    	*p=0xff;
    }
    void main()
    {
    	int a=0x10;
    	printf("\n%x",&a);
    	printf("\n%x\n",a);
    	f(&a);
    	printf("\n%x\n",a);
    }
    



    通过指针传递的案例我们可以看到,调用f(&a)是将a的地址0x12ff44传递给p,则*p就指向了a的内容,改变*p后,a的内容自然就改变了,示意图如下:


    4.指针的引用传递

    void f( int*&p){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	printf("\n%x\n",*p);
    	*p=0xff;
    }
    void main()
    {
    	int a=0x10;
    	printf("\n%x",&a);
    	printf("\n%x\n",a);
    	int *b=&a;
    	printf("\n%x",&b);
    	printf("\n%x",b);
    	printf("\n%x\n",*b);
    	f(b);
    	printf("\n%x\n",a);
    }
    



    为了使用指针的引用传递我们要新建一个指针b,然后将b的引用传递给p,其实p就是b的一个拷贝,*p=*b都指向a,所以改变*p的内容也就改变a的内容。示意图如下:

    我们再来看一下如果不用指针的引用传递会出现什么结果
    void f( int*p){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	printf("\n%x\n",*p);
    	*p=0xff;
    }
    void main()
    {
    	int a=0x10;
    	printf("\n%x",&a);
    	printf("\n%x\n",a);
    	int *b=&a;
    	printf("\n%x",&b);
    	printf("\n%x",b);
    	printf("\n%x\n",*b);
    	f(b);
    	printf("\n%x\n",a);
    	printf("\n%x\n",b);
    }
    


    从结果中我们可以看到调用f(b)时,传递给p的是b的内容,但是&b,和&p是不一样的,虽然*p和*b都指向a。示意图如下:


    5.错误案例


    #include <stdio.h>
    #include <malloc.h>
    #include <string.h>
    
    void Allocate(char* p,int size){
    
    	printf("\n%x",&p);
    	printf("\n%x",p);
    
    	p=(char*)malloc(size);
    }
    void Free(char* p){
    	free(p);
    }
    void main()
    {
    	char *str=NULL;
    	printf("\n%X",&str);
    	printf("\n%X",str);
    	Allocate(str,100);
    	strcpy(str,"Hello World!");
    	printf("\n%s",str);
    	Free(str);
    	printf("\nstr=%s",str);
    	
    }
    



    当执行strcpy(str,"Hello World!"),时会报Unhandled exception in CPoint.exe:0xC0000005:Access Violation,这是因为我们参用的是指针传递,从运行结果我们可以看到str的地址为0x12ff44,当调用Allocate(str,100)时,传递给p的是str,的内容也就是0,所以p为0,但是&p并不是和&str一样的,所以在运行p=(char*)malloc(size)时,是给0x12fef0分配的100个字节,并没有给0x12ff44分配字节,所以*str还是空。所以会报错。

    5.正确案例

    #include <stdio.h>
    #include <malloc.h>
    #include <string.h>
    
    void Allocate(char*& p,int size){
    	printf("\n%x",&p);
    	printf("\n%x",p);
    	p=(char*)malloc(size);
    }
    void Free(char* p){
    	free(p);
    }
    void main()
    {
    	char *str=NULL;
    	printf("\n%X",&str);
    	printf("\n%X",str);
    	Allocate(str,100);
    	strcpy(str,"Hello World!");
    	printf("\n%s",str);
    	Free(str);	
    }
    



    因为指针引用传递的是指针的拷贝,所以&str和&p,是地址是一样的,所以对p分配内容空间也就是对str分配空间,所以没有问题!

    展开全文
  • C语言指针值传递和地址传递

    千次阅读 2020-07-05 21:08:32
    C语言指针传参时,可以通过指针引用方式改变指针指向的值。改变变量,可以使用指针应用方式,改变地址,使用指针的指针引用方式。 C语言值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用...

    C语言传参分为值传传递和地址传递。C语言指针传参时,可以通过指针引用方式改变指针指向的值。改变变量,可以使用指针应用方式,改变地址,使用指针的指针引用方式。

    C语言值传递:

    形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参)

     #include <stdio.h>
     
     void swap(int x, int y);
     
     main()
     {  
        int a = 5, b = 9;
     
         swap(a, b);
        printf("a=%d\nb=%d\n", a, b);
    
        return 0;
    }
    void swap(int x, int y)
    {
        int t;
        t = x;
        x = y;
        y = t;
    }

     上述代码运行后a、b的值并未改变

     

    C语言地址传递:

    形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作

     #include <stdio.h>
     
     void swap(int *p1, int *p2);
     
     main()
     {  
        int a = 5, b = 9;
        int* pointer_1, *pointer_2;
        pointer_1 = &a;
        pointer_2 = &b;
        swap(pointer_1, pointer_2);
        printf("a=%d\nb=%d\n", a, b);
    
        return 0;
    }
    void swap(int *p1, int *p2)
    {
        int t;
    
        t = *p1;
        *p1 = *p2;
        *p2 = t;
    }

    程序说明:

    程序运行时候,先输入a和b的值,然后将a和b的地址赋给指针变量pointer_1和pointer_2,使pointer_1指向a, pointer_2指向b,如图

    在swap函数调用时候,将实参的值传给形参,采用的依然是值传递,虚实结合后形参p1的值为&a,p2的值为&b,这时候p1和pointer_1都指向变量a, p2和pointer_2都指向变量b。

    接着执行swap函数的函数体,使*p1和*p2的值互换,也就是使a和b的值互换,互换后的情况如下

    函数调用结束后,形参p1和p2不复存在(已释放),情况如下

     上述代码执行后a和b值交换,a=9、b=5

     

    易错点补充:

     #include <stdio.h>
     void swap(int *x, int *y);
     
     main()
     {  
        int a = 5, b = 9;
        int *pp = &a;
        int *kk = &b;
        swap(pp, kk);
        printf("a=%d\nb=%d\n", *pp, *kk);
    
        return 0;
    }
    void swap(int *x, int *y)
    {
        int *t;
        t = x;
        x = y;
        y = t;
    }

     请读者想一下,上述代码执行后a和b的值是否交换,为什么?

    上述代码看起来像交换了指针pp和kk的指向,实际上并没有

    代码的运行结果a=5、b=9,运行结果是a和b的值并没有改变,因为这时使用的实参pp,kk是值传递,传递的是指针的值,以指针pp来说,指针的值是变量a的地址,

    指针的值传入后用形参int *x和int *y接收,这里x和pp虽然都指向变量a的地址,但指针变量x和pp自己的地址(地址的地址值)是不相同(意思是x拷贝了一份pp的值),意味着你能改变变量a的值,但是不能改变pp的值(这里与值传递相似)

    为了更加直观,清晰的看出值的交换,这里添加一些代码来显示内存和变量的值

     #include <stdio.h>
     
     void swap(int *x, int *y);
     
     main()
     {
        int a = 10, b = 20;
        int *pp = &a;
        int *kk = &b;
    
        printf("a的地址%p----b的地址%p\n\n", &a, &b);
        printf("pp的值%p----kk的值%p\n", pp, kk);
        printf("pp的地址%p----kk的地址%p\n\n", &pp, &kk);
        swap(pp, kk);
        printf("a = %d\nb = %d", *pp, *kk);
    
       return 0;
    }
    void swap(int *x, int *y)
    {
        int *t;
        
        printf("x的值%p----y的值%p\n", x, y);
        printf("x的地址%p----y的地址%p\n", &x, &y);
    
        t = x;
        x = y;
        y = t;
    }

     

    结构体指针地址传参

    上面的例子只是传递一个int指针类型做参数,看起来比较简单,在实际应用中,结构体指针做函数参数的比较常见,通过结构体指针的引用,可修改结构体成员的数据内容

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

    struct animal
    {  
        char name[30];    
        int num;
    };

    //使用结构体作为参数 浪费内存 需要建立结构体
    void change_struct(struct animal cat)
    {
        cat.num = 17;
    }

    //函数内部改变需要地址 所以需要指针保存
    void change_point(struct animal *cat)
    {
        cat->num   = 13;
    }

    void main
    {
        struct animal cat = {0};
        struct animal *pcat = &cat;
        cat.num = 20;

        change_struct(cat);
        printf("%d",cat.num);  //输出20

        change_point(pcat);
        printf("%d",cat.num);  //输出13

        cat.num = 28;
        change_point(&cat);    //输出13
        printf("%d",cat.num);
    }

    通过上面的例子可以看到,传递结构体指针(或者取它的地址),可以通过结构体指针的引用修改结构体成员的值。直接传递结构体,不能修改结构体成员的值。

    其次,如果传递的是结构体的话,因为C语言的参数传递值调用方式是要求把参数的一份拷贝传递给参数,上面的name这个数组的长度是30,那么这个结构体将占用34个字节的空间,要想把它作为参数传递的,我们必须把34个字节都复制到堆栈中,以后再丢弃,所以传递指针比直接传递结构体变量的效率要高非常多。

    一般,将结构体传递给函数的方式有如下3种:

      1.用结构体的单个成员作为函数参数,向函数传递结构体的单个成员(属于传值调用,不会影响相应的实参结构体的值)

      2.用结构体变量做函数参数,向函数传递结构体完整结构(属于传值调用,不会影响相应的实参结构体的值)

      3.用结构体指针或结构体数组作函数参数属于按引用调用,会影响相应的实参结构体的值,向函数传递结构体地址,因为仅复制结构体首地址一个值给被调函数,相对于第二种方式,这种传递效率更高

     

    总结:

    1. 指针变量只能存表示地址类型的数据

    2. 指针得到谁的地址,就指向谁

    3. 几个指针变量指向同一个地址,通过指针引用改变指向的变量值,其他指针指向的变量值同时也会被改变。地址一样,指向的变量值也一样。

    展开全文
  • 深入理解c++指针的指针和指针...传指针和传指针引用的区别/指针和引用的区别(本质) https://www.cnblogs.com/x_wukong/p/5712345.html 值传递、指针传递、引用传递 https://www.cnblogs.com/happying30/p/94848...
    展开全文
  • 今天我要说的是在学习C语言指针时,在指针变量所指向内存空间所存储的值传递过程中遇到的问题.所谓指针,不用我在这里瞎白话,他就是一种数据类型.指针变量和指针所指向的内存空间是两个不同的概念.指针变量也是一种...
  • C++ 整形 值传递 引用传递 指针传递
  • c++ 函数的参数传递方式有值,指针以及引用三种方式,具体的区别是前两种其实都是值传递,只不过指针是以指针地址值的形式传递的,值传递时,形参是实参的副本,即函数中对形参的修改不会影响到实参的实际值,可以...
  • java中参数传递只有值传递,与java不同,C++中的参数传递方式有三种,分别是 值传递 指针传递和引用传递,值传递指针传递都知识传递当前参数的一个副本,而引用传递则是直接传递参数,所以在函数中改变参数的值就...
  • 要理解值传递、指针传递和引用传递的区别,主要要理解函数的实参和形参,函数的作用域(自动变量、栈),内存的布局...如果需要改变指针本身,可以使用二重指针或者指针引用。引用传递:除了提供输入值外,还返回操作...
  • 文章目录1 C++ 值传递指针传递、引用传递详解值传递指针传递:引用传递:2 数组作为函数的形参2.1 一维数组传递2.2 二维数组传递总结 1 C++ 值传递指针传递、引用传递详解 值传递: 形参是实参的拷贝,改变...
  • C++ 值传递指针传递、引用传递详解
  • C++ 值传递 指针传递 引用传递 简单定义及区别 我们首先给出各种传递方式的简单定义,及各自的区别。 值传递值传递中,形参是实参的拷贝,改变形参的值并不影响外部实参的值。值传递是单向的,及参数的值只能传入...
  • 1) 在数据传输时,如果数据块较大,这时就可以使用指针传递地址而不是实际数据。提高传输速度,又节省大量内存。 2)在数据结构中,链表、树、图等大量的应用都指针。 3)可以动态分配内存。 1)引用是某块内存的...
  • C++ 值传递指针传递、引用传递 最近在学习数据结构中遇到一些困惑,于是参考一些博文后来区分一下函数参数传递的三种方法:值传递指针传递、引用传递. 一、值传递 代码如下: void transfer_value(int n){ n++; ...
  • 使用引用传递的好处:具有值传递的优势,可以向形参传递表达式,让编译器生成临时变量来传递地址;又具有指针传递的优势,实际传递的是地址,提高了速度与效率。 值传递:形参是实参的拷贝,改变形参的值并不会影响...
  • 值传递引用传递,指针传递   值传递引用传递,指针传递:   1、值传递: void f(int x)   传值传的是原来实参的一份拷贝,对形参进行操作不会改变实参的值。函数返回后,函数栈帧销毁,这份拷贝也会自动...
  • C++中的值传递,引用传递及指针传递 C++中的值传递,引用传递及指针传递C++的值传递,引用传递,指针传递这些概念一贯是迷惑C++程序员,我一贯也没有一个能说清他们之间的联络通过一个简略的实例,或许说...
  • 指针有时候真的不是很好懂下面下面我将利用调试的方式讲解一下指针到底是个什么东西 这里我使用了链表结构题 ...说明了当指针作为函数参数传递指针其实就是值传递(也就是把head拷贝一份)如下图: ...
  • 了解值传递/指针传递/引用传递的使用方法。
  • C++ 值传递指针传递、引用传递 值传递 形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入, 不能传出。当函数...
  • 而关于值传递指针传递,引用传递这几个方面还会存在误区, 所有我觉的有必要在这里也说明一下~ 下文会通过例子详细说明哦 值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数...
  • 2.1 值传递值传递是最常规的C语言传参方式。 形参是实参的拷贝,改变形参的值并不会影响外部实参的值。 从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。 当函数内部需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 406,147
精华内容 162,458
关键字:

指针的引用传递