int a = 10;
int *p = &a; // p存储了变量a的地址,定义指针变量的同时进行赋值
int a = 10;
int *p;
p = &a;//先定义指针变量,之后再进行赋值
注意:int *p和*p的区别
int *p
:声明一个指针变量 p
,它专门用于存储 int
类型变量的地址
*p
(解引用指针,即通过指针找到它指向的内存地址的实际数据)
int *p = &a; 这个代码的解释:
-
int *p
:声明一个指针变量p
,它专门用于存储int
类型变量的地址。 -
= &a
:将变量a
的地址赋值给指针p
。 -
此处的
int *p不是解引用的意思
*p
(解引用指针,即通过指针找到它指向的内存地址的实际数据)
-
含义:
*p
表示访问指针p
指向的内存地址中存储的值。 -
结果:打印
*p
会输出a
的值,即 10。
p
(指针本身)
-
含义:
p
存储的是变量a
的内存地址。 -
结果:打印
p
会输出一个十六进制表示的地址值(如0x7ffd42c8a9fc
),具体值取决于系统和运行时内存分配。
&a
(表示取变量 a
的内存地址)
含义:表示取变量 a
的内存地址
&*p(等价于p)
-
先对指针
p
解引用(*p
),获取其指向的值。 -
再对解引用后的值取地址(
&
),即获取该值的内存地址。
为什么c语言需要使用指针
例子:交换两个变量的函数
不使用指针:
void swap(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}
int main() {
int x = 1, y = 2;
swap(x, y); // 仅交换副本,x和y的值不变
printf("x=%d, y=%d\n", x, y); // 输出 x=1, y=2
return 0;
}
为什么会失败呢?
在C语言中,函数参数传递是值传递(Pass by Value),而不是引用传递(Pass by Reference)。这是导致你的 swap
函数无法交换 x
和 y
的根本原因。以下是详细解释:
1. 值传递的本质
当调用 swap(x, y)
时,实际发生的是:
-
实参
x
和y
的值被复制一份。 -
形参
a
和b
接收的是这些副本,而不是原始变量本身。
内存模型示例:
变量 | 内存地址 | 初始值 | 调用 swap(x, y) 后 |
---|---|---|---|
x | 0x1000 | 1 | 仍为 1 |
y | 0x1004 | 2 | 仍为 2 |
a | 0x2000 | 1 (复制) | 被修改为 2 |
b | 0x2004 | 2 (复制) | 被修改为 1 |
-
关键:
a
和b
是独立于x
和y
的副本,修改a
和b
不会影响原始变量x
和y
。
2. 函数调用的分步解析
(1) 调用 swap(x, y)
时
-
a
被赋值为x
的副本(1
)。 -
b
被赋值为y
的副本(2
)。
(2) 在 swap
函数内部
-
tmp = a
→tmp = 1
。 -
a = b
→a = 2
。 -
b = tmp
→b = 1
。
(3) 函数返回后
-
形参
a
和b
被销毁。 -
原始变量
x
和y
未发生任何变化。
替代方法1:使用全局变量(不推荐),破坏了函数的封装性,依赖全局状态。
int x, y;
void swap_global() {
int tmp = x;
x = y;
y = tmp;
}
int main() {
x = 1, y = 2;
swap_global();
printf("x=%d, y=%d\n", x, y); // 输出x=2, y=1
return 0;
}
替代方法2:使用指针(推荐),指针传递的是变量的地址,通过地址可以直接操作原始内存中的数据
#include <stdio.h>
// 交换两个整数的函数
void swap(int *a, int *b) {
int tmp; // 临时变量用于暂存值
tmp = *a; // 将a指向的值存入tmp
*a = *b; // 将b指向的值赋给a指向的地址
*b = tmp; // 将tmp的值赋给b指向的地址
}
int main(void) {
int x = 1, y = 2;
printf("交换前: x=%d, y=%d\n", x, y); // 输出交换前的值
swap(&x, &y); // 传递x和y的地址给swap函数
printf("交换后: x=%d, y=%d\n", x, y); // 输出交换后的值
return 0;
}