0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言指针作为形参怎么改变其指向的地址

Q4MP_gh_c472c21 来源:ERYUESANHI 作者:ERYUESANHI 2021-10-09 11:54 次阅读

就是一个函数的输入参数是一个指针,该函数需要改变该指针指向的地址,如: 现在有一个全局数组b,现在需要编写一个函数 输入参数是一个指针a,需要通过该函数将该指针a指向数组b,即:

intb[3]={1,2,3};

voidfcn(参数);

voidmain()
{
int*a;
fcn(输入参数a)

}

执行完fcn后,使参数的地址改变,这个功能怎么来实现呢?

首先说明结论:使用二级指针。

为了更好的理解这个问题,我们首先来学习一下指针最经典的例子,交换两个数来说明函数的形参和实参之间的关系。

首先来探究以下实参和形参的关系是怎样的。

形参为普通变量类型;

voidtest1(inta,intb)
{
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);//打印形参地址
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);//打印形参值
}

intmain()
{
inta=1,b=2;

printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
test1(a,b);

return0;
}

下面是执行结果:

>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:1,actualvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:1,formalvalueb:2

可以看到形参和实参的值虽然相同,但是他们的地址却不相同,所以函数在被调用的时候传入的参数(实参)实际上是被复制到另一个地址(形参地址)中去了,函数中对传入参数的操作实际上是对形参地址中的数进行操作,而与实参无关。所以下面的函数不能实现交换两个数的功能。

voidswap_1(inta,intb)
{
inttemp;
temp=a;
a=b;
b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
}

intmain()
{
 int a = 1, b = 2;
swap_1(a,b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}

输出如下:

>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:2,formalvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:1,actualvalueb:2

可以看到在swap_1函数中a,b两个数的值是被调换了的,但是函数中的a,b的地址和主函数中a,b的地址根本不是同一个,主函数中a,b还是原来的数,所以这个函数起不到交换两个数功能。

既然形参和实参的关系是地址不同而值相同那么我们将实参的地址当作参数传给形参,然后在函数中对形参所指向的地址中的值(该地址就是实参的地址)进行改变是否就可以完成两个数的交换了?

OK!下面我们来编写函数测试以下:

voidswap_2(int*a,int*b)
{
inttemp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);//打印形参地址
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);//打印形参的值
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);//打印以形参值为地址的值
temp=*a;
*a=*b;
*b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
}

intmain()
{
inta=1,b=2;
swap_2(&a,&b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}

结果如下:

>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:1,formaladdrvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:2,formaladdrvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:2,actualvalueb:1

从结果可以看出,这个函数可以交换输入参数的值。下面我们来分析一下为什么这个函数能够实现交换功能。

以变量a为例,首先,从结果的第一行可以看出,传入函数的参数是地址(即实参a的地址:6420300),这个地址作为一个值存放在形参a(地址:6422272)中,然后定义一个int型变量来存放地址6422272(形参a的地址)中的值6422300(实参a的地址),然后将指向6422296(实参b的地址)地址中的值 赋给 指向6422300(实参a的地址),开始地址6422300地址中的值为2,现在该地址的值变为1,同理,在执行函数之后地址6422296中的值变为1,从而实现了两个数的交换。

在这个过程中,是函数调用a,b两个值的地址,并在函数中改变这两地址中的值。与上一个函数的本质区别就是:上一个函数swap1只是将a,b的值给复制到两个新的地址当中,并改变新的地址中的值,与a,b地址无关。而swap_2则是直接操作a,b地址中的值,进而可以实现交换两个数的功能。

注意:实参和形参是在两个不同地址,虽然起的名字是一样的,当然这个名字可以自己随意起。为了更加清楚的说明实参和形参是两个东西,下面我将形参的变量名给改一下:

voidswap_2(int*formal_a,int*formal_b)
{
inttemp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
temp=*formal_a;
*formal_a=*formal_b;
*formal_b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
}

intmain()
{
inta=1,b=2;
swap_2(&a,&b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}

结果如下:

>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:1,formaladdrvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:2,formaladdrvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:2,actualvalueb:1

和之前的结果一样,可以知道,函数在执行的时候其实是不管你名字怎么起的,而是关心地址,而你起的名字实际也只是那个地址的代号而已。

通过上面的例子已经清楚了函数的形参与实参的区别,那么现在就来解决文章开头提出的问题

如何通过函数改变一个传入指针作为实参的地址,其实在理解上面的关于函数的形参和实参就非常容易懂了。

首先我们来看下面一个例子

intb[3]={1,2,3};

voidfcn(int**a)
{
*a=b;
}

intmain()
{
unsignedinti=0;
int*a;

for(i=0;i<3;i++)
     {
         printf(">>%d
",a[i]);
}

fcn(&a);

for(i=0;i<3;i++)
     {
         printf(">>%d
",a[i]);
}
}

函数输出为:

>>0
>>-1
>>4194304
>>1
>>2
>>3

主函数中,我们定义了一个指针a,并且没有初始化它,之后我们是不能够直接对它指向的地址进行赋值,因为现在它的地址是随机的,对该地址进行操作后有可能会导致程序崩溃。我们想要用它就只能够对它自己的值也就是它所指向的地址进行操作。函数fcn通过形参来改变输入实参的值是怎么做到的呢?

首先看函数的形参(int **a),表示什么意思呢?就是说传入的一个二级指针,指向指针的指针,这又是什么意思呢?比如你有一张藏宝图,它说宝藏在a地,你到a地之后也只得到一张藏宝图,该藏宝图说宝藏在b地,你只有到达b地才能够得到宝藏。这就是一个二级指针,第一个指向的地址是a,a的内容也是一个指针,指向b,b地址下才是真正的内容。

我们在主函数中定义了一个指针a,让它传入函数fcn,我们分析一下这个过程:

函数开辟一个形参的地址,该地址中的内容为指向传入参数地址的值,那么函数中我们将数组b的首地址赋给该地址,也就是将实参的地址更改成了数组b的首地址。

文章确实太绕了,个人觉得最主要的点就是弄清楚指针与地址以及该地址的值的关系,还有就是形参与实参的关系。

编辑:jq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136788
  • 函数
    +关注

    关注

    3

    文章

    4331

    浏览量

    62593
  • 指针
    +关注

    关注

    1

    文章

    480

    浏览量

    70560

原文标题:C语言指针作为形参如何改变其指向的地址?

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    c语言指针

    1:指针是一个地址指向的是个类型:我们知道,c语言中的类型有int,char,bool(这个不常用),一般我们使用int,char就可以满
    发表于 09-19 00:12

    函数指针指针函数

    ) ([列表]); 注1:“返回值类型”说明函数的返回类型,“(指针变量名 )”中的括号不能省,括号改变了运算符的优先级。若省略整体则成为一个函数说明,说明了一个返回的数据类型是
    发表于 01-22 19:28

    C语言入门教程-指向同一地址

    指向同一地址 C语言的一个优点是:任意多个指针可以指向同一内存
    发表于 07-29 11:45 1092次阅读

    C语言入门教程-指向结构体的指针

    指向结构体的指针C语言中几乎可以创建指向任何类型的指针,包括用户自定义的类型。创建结构体
    发表于 07-29 12:04 3153次阅读

    C语言入门教程-指向指针指针

    指向指针指针 创建一个指针,使它指向另一个指针,这是可能的,而且常常也是必要的。这一技术有时
    发表于 07-29 12:10 1096次阅读

    C语言教程之函数指针变量与指针函数的区别(下篇)

    z=(*pfun)(x,y); //调用函数指针变量,实参x和y的值传递给a和b printf(“max=%dn”,z); //a
    发表于 05-22 07:30 1992次阅读

    C语言初识指针

    目录1. 指针是什么?2. 指针指针类型3.野指针3.1 野指针成因3.2 如何规避野指针4.
    发表于 12-31 19:57 26次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>初识<b class='flag-5'>指针</b>

    C语言指针的理解使用

    C语言指针的理解使用指针变量的声明给普通变量的赋值对比给指针变量的赋值代*的指针的使用说明
    发表于 01-13 13:42 3次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>指针</b>的理解使用

    C语言中的指针(重点)超详细

    - 指针4.3、指针的运算关系5、指针和数组6、二级指针7、指针数组1、指针是什么??在计算机
    发表于 01-13 14:10 11次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>中的<b class='flag-5'>指针</b>(重点)超详细

    C语言-函数的可变形(不定形)

    这篇文章介绍C语言函数的不定参数、可变参数 ,实现printf一样的传效果。
    的头像 发表于 08-14 09:58 2670次阅读

    C语言-指针作为函数类型

    C语言函数里最常用就是指针和返回地址,特别是字符串处理中,经常需要封装各种功能函数完成数据处理。
    的头像 发表于 08-14 10:05 1895次阅读

    指针进阶第五站:函数指针

    定义一个函数指针指向的函数有两个int并且返回一个函数指针,返回的指针
    发表于 08-17 15:58 535次阅读

    C语言指针详细解析

    可以对数据本身,也可以对存储数据的变量地址进行操作。 指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。在C/C++语言中,
    的头像 发表于 11-14 16:53 2220次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>指针</b>详细解析

    C语言怎样引用指针变量

    指针C语言中的一个重要概念,也是C语言的一个重要特色。正确而灵活地运用它,可以使程序简洁、紧凑、高校。 由于通过
    的头像 发表于 03-10 14:43 1051次阅读

    C语言数组元素的指针

    C语言调用函数时虚实结合的方法都是采用“值传递”方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时。 由于数组名代表的是数组元素
    的头像 发表于 03-10 14:45 910次阅读