目录
引言
一、值传递(Pass by Value)
1.1 基本概念
1.2 代码示例
1.3 内存图解
二、地址传递(Pass by Address)
2.1 本质解析
2.2 经典示例
2.3 内存变化
三、两种方式的对比
四、数组参数的秘密
4.1 数组传参的本质
4.2 典型误区
五、最佳实践指南
六、常见错误案例分析
错误1:试图通过值传递修改外部变量
错误2:空指针解引用
总结
在C语言中,函数的参数传递方式是理解程序行为的关键。许多初学者在使用函数时,常常对“为什么修改参数的值不影响原变量”或“如何通过函数真正改变外部变量”感到困惑。本文将深入探讨C语言中值传递和地址传递的核心机制,并通过实际代码示例揭示它们的差异和应用场景。
值传递是C语言中默认的参数传递方式。其核心特点是: 函数内部得到的是参数的副本 对参数的修改不会影响原变量
#include
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("函数内交换后:a=%d, b=%d\n", a, b);
}
int main() {
int x = 10, y = 20;
swap(x, y);
printf("main函数中交换后:x=%d, y=%d\n", x, y);
return 0;
}
/* 输出:
函数内交换后:a=20, b=10
main函数中交换后:x=10, y=20
*/
调用前 main栈帧:
x(0x1000): 10
y(0x1004): 20
swap栈帧创建后:
a(0x2000): 10 ← x的副本
b(0x2004): 20 ← y的副本
地址传递通过指针实现,本质仍是值传递(传递指针变量的值),但可以通过地址间接修改原数据: 传递变量的内存地址 函数通过解引用操作符*
访问实际内存
#include
void real_swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
real_swap(&x, &y);
printf("x=%d, y=%d\n", x, y); // 输出:x=20, y=10
return 0;
}
main栈帧:
x(0x1000): 10 → 20
y(0x1004): 20 → 10
real_swap栈帧:
a(0x2000): 0x1000 ← 存储x的地址
b(0x2004): 0x1004 ← 存储y的地址
特性 |
值传递 |
地址传递 |
传递内容 |
变量的值 |
变量的内存地址 |
内存消耗 |
复制整个数据 |
固定4/8字节(指针大小) |
对原数据的影响 |
无法修改 |
可以修改 |
典型应用场景 |
基本数据类型(int, char等) |
数组/结构体/需要修改的变量 |
安全性 |
高 |
需注意空指针问题 |
虽然看起来像值传递,但数组名作为参数时实际传递的是首元素地址:
void printArray(int arr[], int size) {
// 等价于 int *arr
for(int i=0; i
void wrong_size(int arr[5]) {
// sizeof(arr)返回指针大小,不是数组总大小!
printf("%zu\n", sizeof(arr)); // 输出8(64位系统)
}
void read_data(const int *ptr) {
*ptr = 10; // 编译错误!受到const保护
}
void increment(int a) {
a++; // 仅修改副本
}
int main() {
int num = 5;
increment(num);
printf("%d", num); // 仍然输出5
}
void dangerous(int *p) {
*p = 10; // 若p为NULL会导致段错误
}
理解参数传递机制是成为C语言高手的必经之路:
✅ 值传递保护原数据,适合小型数据✅ 地址传递高效灵活,但需要谨慎使用✅ 数组传参本质是指针传递✅ 合理使用const保护关键数据
掌握这些核心概念后,读者可以更自信地编写高效、安全的C语言代码!