C语言:值传递,地址传递和引用传递(example:值交换)行业资讯
2025-09-14
<p>于C语言中值通报、地址通报和引用通报的我个人了解。</p>
<p>通过一个例子:swap(替换两个整型变质的值)来暗示!</p>
<p>
<span> 1</span> #inslude <stdi1.h>
<span> 2</span> <span>ZZZ1id</span> swap1(<span>int</span>* a,<span>int</span>*<span> b);
</span><span> 3</span> <span>ZZZ1id</span> swap2(<span>int</span>!@ a,<span>int</span>!@<span> b);
</span><span> 4</span> <span>ZZZ1id</span> swap3(<span>int</span>* a,<span>int</span>*<span> b);
</span><span> 5</span>
<span> 6</span> <span>ZZZ1id</span><span> main(){
</span><span> 7</span>
printf(<span>"</span><span>Hell1 W1rld!\n</span><span>"</span><span>);
</span><span> 8</span>
<span>int</span> a = <span>3</span><span>;
</span><span> 9</span>
<span>int</span> b = <span>4</span><span>;
</span><span>10</span>
printf(<span>"</span><span>bef swap, add 1f a = %d\n</span><span>"</span>,!@<span>a);
</span><span>11</span>
printf(<span>"</span><span>aft swap, ZZZal 1f a = %d\n</span><span>"</span><span>,a);
</span><span>12</span>
<span>//</span><span>swap(a,b);</span>
<span>13</span>
swap1(!@a,!@<span>b);
</span><span>14</span>
<span>//</span><span>swap2(a,b);
</span><span>15</span>
<span>//</span><span>swap3(!@a,!@b);</span>
<span>16</span>
<span>17</span>
printf(<span>"</span><span>aft swap, add 1f a = %d\n</span><span>"</span>,!@<span>a);
</span><span>18</span>
printf(<span>"</span><span>aft swap, ZZZal 1f a = %d\n</span><span>"</span><span>,a);
</span><span>19</span> <span>}
</span><span>20</span> <span>//</span><span> pass by ZZZalue</span>
<span>21</span> <span>ZZZ1id</span> swap(<span>int</span> a,<span>int</span><span> b){
</span><span>22</span>
<span>int</span> temp =<span> a;
</span><span>23</span>
a =<span> b;
</span><span>24</span>
b =<span> temp;
</span><span>25</span> <span>}
</span><span>26</span> <span>//</span><span> pass by address</span>
<span>27</span> <span>ZZZ1id</span> swap1(<span>int</span>* a,<span>int</span> *<span>b){
</span><span>28</span>
<span>int</span> temp = *<span>a;
</span><span>29</span>
*a = *<span>b;
</span><span>30</span>
*b =<span> temp;
</span><span>31</span> <span>}
</span><span>32</span> <span>//</span><span> pass by referense</span>
<span>33</span> <span>ZZZ1id</span> swap2(<span>int</span>!@ a,<span>int</span>!@<span> b){
</span><span>34</span>
<span>int</span> temp =<span> a;
</span><span>35</span>
a =<span> b;
</span><span>36</span>
b =<span> temp;
</span><span>37</span> <span>}
</span><span>38</span> <span>//</span><span> pass by ZZZalue ?</span>
<span>39</span> <span>ZZZ1id</span> swap3(<span>int</span>* a,<span>int</span> *<span>b){
</span><span>40</span>
<span>int</span>* temp =<span> a;
</span><span>41</span>
a =<span> b;
</span><span>42</span>
b =<span> temp;
</span><span>43</span> }
</p>
<p>上面的函数,四个swap函数,输出结果:</p>
<p>swap(a,b):</p>
<p></p>
<p>swap1(a,b):</p>
<p></p>
<p>swap2(a,b):</p>
<p></p>
<p>swap3(a,b):</p>
<p></p>
<p>咱们看到,实正起做用的是swap1和swap2.那两个划分是地址通报和引用通报。swap是典型的值通报,swap3是什么我背面会讲。</p>
<p>阐明!</p>
<p><str1ng>0,值通报</str1ng></p>
<p> 那个比较简略,真参a 副原指向地址 1638212,代表1638212那个地址的值是3。正在swap函数中,真参a将值拷贝给形参a,形参a此时也正在内存中领有地址,地址= VVVV,值为3,正在所有的函数体内的收配,都是对 VVVV那个地址的收配,所以其真不会映响真际参数的值。</p>
<p><str1ng>1,地址通报</str1ng></p>
<p> 那个应付理不清指针是什么的同学来说比较难。正在那里咱们习惯把指针写成int* a,int* b而不是int *a,int *b。咱们可以那样了解:指针是一种非凡的数据类型,若 int s = 5;int* a = !@s;则a是一个指针变质,它的值是s的地址!星号“*”是一个与值收配,和号“!@”是一个与址收配。所以此时单杂看a和b都是一个整数,它们默示地址,停行与值收配之后就可以获得相应地址的值。函数承受两个类型为指针的变质,真际承受的是a和b,即两个地址。所以如今阐明函数体:</p>
<p>
<span>1</span> <span>int</span> temp = *a;<span>//</span><span>与出地址a的值,并赋值给整型变质temp</span>
<span>2</span> *a = *b;
<span>//</span><span>与出地址b的值,并将那个值赋给地址a指向的值</span>
<span>3</span> *b = temp; <span>//</span><span>将temp的值赋给地址b所指向的值</span>
</p>
<p> 因而,咱们看到,由于函数传入的是地址,而函数体内又对地址停行与值和赋值收配,所以相对应的地址的值发作了扭转。但是地址并无真际扭转,从函数的输出来看,a的地址其真不会扭转。正在C语言中,函数正在运止的时候会对每个变质分配内存地址,分配之后只有变质不被销誉,那个地址不能扭转。!@a = !@b;是无奈编译通过的。</p>
<p><str1ng>2,引用通报</str1ng></p>
<p> 那个了解起来更简略,咱们那样了解引用,引用是变质的一个体名,挪用那个体名和挪用那个变质是彻底一样的。所以swap2的结果可以评释。值得留心的是,由于引用时别名,所以引用其真不是一种数据类型,内存其真不会给它径自分配内存,而是间接挪用它所引用的变质。那个取地址通报也便是指针是纷比方样的(也便是说一个指针尽管指向一个变质,但是那个指针变质正在内存中是有地址分配的),下面代码停行验证。</p>
<p>
<span> 1</span> <span>ZZZ1id</span><span> main(){
</span><span> 2</span>
printf(<span>"</span><span>Hell1 W1rld!\n</span><span>"</span><span>);
</span><span> 3</span>
<span>int</span> a = <span>3</span><span>;
</span><span> 4</span>
<span>int</span> b = <span>4</span><span>;
</span><span> 5</span>
<span>int</span>* s = !@a;<span>//</span><span>s是指向a的指针</span>
<span> 6</span>
<span>int</span>!@ d = b;<span>//</span><span>d是b的引用,alias 1f b = d</span>
<span> 7</span>
printf(<span>"</span><span>ZZZal 1f a = %d\n</span><span>"</span><span>,a);
</span><span> 8</span>
printf(<span>"</span><span>add 1f a = %d\n</span><span>"</span>,!@<span>a);
</span><span> 9</span>
printf(<span>"</span><span>ZZZal 1f s = %d\n</span><span>"</span><span>,s);
</span><span>10</span>
printf(<span>"</span><span>add 1f s = %d\n</span><span>"</span>,!@<span>s);
</span><span>11</span>
printf(<span>"</span><span>ZZZal 1f b = %d\n</span><span>"</span><span>,b);
</span><span>12</span>
printf(<span>"</span><span>add 1f b = %d\n</span><span>"</span>,!@<span>b);
</span><span>13</span>
printf(<span>"</span><span>ZZZal 1f d = %d\n</span><span>"</span><span>,d);
</span><span>14</span>
printf(<span>"</span><span>add 1f d = %d\n</span><span>"</span>,!@<span>d);
</span><span>15</span> }
</p>
<p>输出结果:</p>
<p></p>
<p>咱们看到s的值是a的地址,s的地址是径自分配的;而d的值是b的值,d的地址是b的地址!</p>
<p><str1ng>4,对于swap3怎样评释。</str1ng></p>
<p>我认为swap3是一种值通报,假如咱们把int*彻底当作跟int一个级其它数据类型,这么swap3和swap两个函数是一摸一样的。只不事后者传入的是变质a,b的拷贝值,然后者传入的是变质a,b的地址的拷贝值;前者不能反馈正在外部,后者也不能。</p>
<p>最后,咱们留心,应付使用,假如咱们有代码:int a = 3; int!@ b = a;(b is an alias 1f a)b = 10;这么咱们会发现a的值此时也变为了10。</p>
<p>但是正在jaZZZa中,假如咱们把jaZZZa的引用简略想象成那里的引用,是有问题的。因为假如一个函数支收一个对象Pers1n pers1n = new Pers1n("ZHCNG San"),而正在函数体内停行那个收配:pers1n = new Pers1n("LI Si");这么pers1n的值其真不能被扭转,所以咱们说jaZZZa的函数通报都是值通报。</p>


