【C/C++】 函数形参—指针传递
【C/C++】 函数形参—指针传递
🌈最近又复习了一下关于函数和指针传递的内容,现在再分享一下~
首先要了解一下函数传入参数的一个基本的过程。
🌞在 C 语言中,函数参数传递是值传递:形参是实参的副本,修改形参不会影响实参。 当需要在函数中访问另一个函数的数据时,可以把指针作为函数的参数,但如果参数是指针,函数内部可以通过指针解引用修改原变量的值
- 值传递:函数里玩的是“复印件”。
- 指针/引用:函数里玩的是“原件本身”。
下面用数值交换为例说明。
#include <iostream>
using namespace std;struct Solution {/*1. 指针传递 —— 真正交换 */void swap(int *a, int *b) {cout << "=== swap(int *a, int *b) ===\n";cout << "a 指向 " << a << " b 指向 " << b << endl;int tmp = *a;*a = *b;*b = tmp;}/* 2. 值传递 —— 换了个寂寞 */void swap(int a, int b) {cout << "=== swap(int a, int b) 值传递 ===\n";cout << "形参 a 地址 " << &a << " 形参 b 地址 " << &b << endl;int tmp = a;a = b;b = tmp;}
};int main() {int a = 3, b = 44;Solution s;cout << "原始值 a=" << a << " b=" << b << endl;cout << "它们地址 &a=" << &a << " &b=" << &b << "\n\n";// 3. 值传递(失败)s.swap(a, b);cout << "值传递后 a=" << a << " b=" << b << "\n\n";// 2. 指针传递(成功)s.swap(&a, &b);cout << "指针传递后 a=" << a << " b=" << b << "\n\n";return 0;
}
下面是运行的结果
原始值 a=3 b=44
它们地址 &a=0x7ffeef2f69a8 &b=0x7ffeef2f69ac=== swap(int a, int b) 值传递 ===
形参 a 地址 0x7ffeef2f6998 形参 b 地址 0x7ffeef2f699c
值传递后 a=3 b=44=== swap(int *a, int *b) ===
a 指向 0x7ffeef2f69a8 b 指向 0x7ffeef2f69ac
指针传递后 a=44 b=3
传递模拟
main函数栈和 要跳转的函数栈是两个地方,函数传参的时候,会把main里面的变量的值在函数栈复制一份:1️⃣对于值传递而言,复制的是值本身;2️⃣对于指针传递而言,复制的是指针变量的值,也就是一个地址。
**在 C 语言中,函数参数传递是值传递:形参是实参的副本,修改形参不会影响实参。**也就是函数一旦结束运行,里面的变量都会被释放,所以修改形参不会影响实参。
那么为什么传入指针可以修改变量捏?在函数中访问另一个函数的数据时,可以把指针作为函数的参数,但如果参数是指针,函数内部可以通过指针解引用修改原变量的值
也就是通过操作指针变量的值,也就是地址,解引用修改原变量的值,这样就可以通过指针直接操作原变量的值,实现修改的目的。
A) 值传递版 void swap(int a, int b)
main 栈帧
+---------------+ 高地址
| …… |
| int b = 44 | 0x7ffe6b4829ac <─ 原件
| int a = 3 | 0x7ffe6b4829a8 <─ 原件
+---------------+
| ret addr |
+---------------+
swap 栈帧
| int b = 44(传入的是值 44) | 0x7ffe6b48296c <─ 副本(换的是它)
| int a = 3 (传入的是值 3) | 0x7ffe6b482968 <─ 副本
| int tmp |
+---------------+ 低地址→ 交换后只改副本,main 的 0x7ffe6b4829a8/0xac 纹丝不动。
B) 指针版 void swap(int *a, int *b)
main 栈帧
+---------------+
| int b = 44 | 0x7ffe6b4829ac
| int a = 3 | 0x7ffe6b4829a8
+---------------+
(传的是地址 可以通过这个地址更改原变量的值)
swap 栈帧
| int *b 0x7ffe6b4829ac | <─ 存的是 main.b 的地址
| int *a 0x7ffe6b4829a8 | <─ 存的是 main.a 的地址
| int tmp |
+---------------+→ 通过 *a / *b 直接改 0x7ffe6b4829a8 / 0xac 处的值,原件被换。
🌿 完结~