其实这个是超级经典的问题啦,就是自己定义一个函数 swap,如果是这样写的话那么无法完成交换
1 | int swap(int x, int y){ |
这样是达不到效果的,x 和 y 依然没法交换,但如果换个方式就可以
1 | int swap(int *x, int *y){ |
这样就可以,嗯一般的解释是它传入的是地址不是值所以可以交换,不过听起来很玄乎是吧?so,其中有俩要明确一下的
1. 无论如何都是传值,c 语言并没有传入地址一说,传入指针也是传值!
2. 传入的 var 是无法被改变的,传入的指针也没有改变!因此你如果要改变一个指针,就只能再创建一个指向这个指针的指针!
函数参数在传递的时候,都是传原数据的副本,也就是说,swap 内部使用的 a 和 b 只是最初始x和y的一个副本而已,所以无论在 swap 函数内部对 x 和 y 做任何改变,都不会影响初始的 x 和 y 的值。
正因如此,我们常常被告知,不要把直接把结构体直接作为参数,这样效率会很低。由于结构体本身占用字节数较大,如果直接作为参数,那么将会产生一个较大的”副本“,如此一来,效率也就很低了。然而指针的大小基本上是固定的,取决于你运行的硬件,在一个平台上是固定的。
所以话说回来,为什么传入指针就可以改变呢?其实刚刚的函数省略了一些
1 | int main(){ |
太长不看
它传入的是指针变量,所以这个函数并没有去改变这俩指针的值,而是直接访问了这俩指针的值 —— which is 这两个 var 的虚拟地址(没错不是真实地址,为了方便访问的地址而已),利用这个值的地址,去改变了这个地址里面的东西。
所以同理可得,如果你需要改变一个指针变量的值(是的,指针变量和普通的变量没有区别,只是它的值是另一个值的地址),那么你就需要另一个存储了这个变量地址的变量,直接访问这个变量去改变~
其实说着有点绕嗷,反正就是记住传入函数的值的更改是不可饶恕的就可以了,黑之历史的函数的更改不可饶恕嗷!要更改只能间接加入另一个变量。
ref: