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

    文章

    7521

    浏览量

    127409
  • 函数
    +关注

    关注

    3

    文章

    3859

    浏览量

    61296
  • 指针
    +关注

    关注

    1

    文章

    469

    浏览量

    70360

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

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

收藏 人收藏

    评论

    相关推荐

    大话指针变量的定义

    ,int_array_p指向整型一维数组,同时这个数组必须只能有10个元素,偏移量为整个数组所占字节数4*10,function_p指向一个函数的入口地址,只能指向
    发表于 09-24 01:01

    c语言指针

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

    C语言——指针、数组和函数

    C语言——指针、数组和函数基本解释   1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(
    发表于 04-20 15:25

    函数指针指针函数

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

    C语言指针详解

    ];//指针的类型是 int(*)[3] (5)int*(*ptr)[4];//指针的类型是int*(*)[4] 怎么样?找出指针的类型的方法是不是很简单? 完整的C
    发表于 07-04 03:34

    c语言指针详解

    1.指针简介 指针C语言中广泛使用的一种数据类型。 运用指针编程是C
    发表于 03-26 09:51

    关于嵌入式C语言指针的学习笔记

    这段时间快马加鞭学习嵌入式C语言,在此留点关于指针的笔记最普通的指针:int *a;调用形式:1、a——a指向的对象的
    发表于 12-14 08:27

    嵌入式c语言指针指向常量相关资料分享

    UINT8 *p1 = "hello";UINT8 *p2="hello";如上代码中p1与p2是否指向同一地址?运行调试:可以看出p1和p2是指向同一地址
    发表于 01-24 06:32

    proteus双刀开关怎么改变开关的指向呢?

    proteus双刀开关怎么改变开关的指向呢?
    发表于 04-24 17:42

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

    指向同一地址 C语言的一个优点是:任意多个指针可以指向同一内存地址。例如,下面的代码声明p、q
    发表于 07-29 11:45 974次阅读

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

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

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

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

    C语言初识指针

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

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

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

    C语言数组和指针的区别

    指针是一个变量,它存储了一个内存地址,该地址指向一个变量的存储位置。通过指针,可以访问和修改指向
    的头像 发表于 05-30 10:55 546次阅读
    C<b class='flag-5'>语言</b>数组和<b class='flag-5'>指针</b>的区别