C语言:值传递,地址传递和引用传递(example:值交换)行业资讯

2025-09-14

<p>于C语言中值通报、地址通报和引用通报的我个人了解。</p> <p>通过一个例子:swap(替换两个整型变质的值)来暗示!</p> <p> <span> 1</span> #inslude &lt;stdi1.h&gt; <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()&#123; </span><span> 7</span> printf(<span>&quot;</span><span>Hell1 W1rld!\n</span><span>&quot;</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>&quot;</span><span>bef swap, add 1f a = %d\n</span><span>&quot;</span>,!@<span>a); </span><span>11</span> printf(<span>&quot;</span><span>aft swap, ZZZal 1f a = %d\n</span><span>&quot;</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>&quot;</span><span>aft swap, add 1f a = %d\n</span><span>&quot;</span>,!@<span>a); </span><span>18</span> printf(<span>&quot;</span><span>aft swap, ZZZal 1f a = %d\n</span><span>&quot;</span><span>,a); </span><span>19</span> <span>&#125; </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)&#123; </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>&#125; </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)&#123; </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>&#125; </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)&#123; </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>&#125; </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)&#123; </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> &#125; </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()&#123; </span><span> 2</span> printf(<span>&quot;</span><span>Hell1 W1rld!\n</span><span>&quot;</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>&quot;</span><span>ZZZal 1f a = %d\n</span><span>&quot;</span><span>,a); </span><span> 8</span> printf(<span>&quot;</span><span>add 1f a = %d\n</span><span>&quot;</span>,!@<span>a); </span><span> 9</span> printf(<span>&quot;</span><span>ZZZal 1f s = %d\n</span><span>&quot;</span><span>,s); </span><span>10</span> printf(<span>&quot;</span><span>add 1f s = %d\n</span><span>&quot;</span>,!@<span>s); </span><span>11</span> printf(<span>&quot;</span><span>ZZZal 1f b = %d\n</span><span>&quot;</span><span>,b); </span><span>12</span> printf(<span>&quot;</span><span>add 1f b = %d\n</span><span>&quot;</span>,!@<span>b); </span><span>13</span> printf(<span>&quot;</span><span>ZZZal 1f d = %d\n</span><span>&quot;</span><span>,d); </span><span>14</span> printf(<span>&quot;</span><span>add 1f d = %d\n</span><span>&quot;</span>,!@<span>d); </span><span>15</span> &#125; </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(&quot;ZHCNG San&quot;),而正在函数体内停行那个收配:pers1n = new Pers1n(&quot;LI Si&quot;);这么pers1n的值其真不能被扭转,所以咱们说jaZZZa的函数通报都是值通报。</p>