1.1 内存地址的概念
每个变量存储在内存的某个位置,内存地址用十六进制数表示(如0x7ffeed3a4b58),指针变量专门用来存储内存地址。
1.2 指针的定义
int var = 10; // 普通变量
int *ptr = &var; // 指针变量,指针ptr指向var的地址
&
:取地址运算符
*
:指针声明符/解引用运算符
2.1 基础操作示例
int a = 5;
int *p = &a; // p存储a的地址,*为声明指针
printf("a的值:%d\n", a); // 输出5
printf("a的地址:%p\n", &a); // 输出类似0x7ffeeb4b3c
printf("p的值:%p\n", p); // 同上地址
printf("*p的值:%d\n", *p); // 输出5(*为解引用)
2.2 修改指向的值
*p = 20; // 通过指针修改原始变量
printf("现在a的值是:%d", a); // 输出20
3.1 算术运算
int arr[5] = {10,20,30,40,50};
int *ptr = arr; // 等价于&arr[0],因为数组名称等于数组首元素的地址。
printf("%d\n", *ptr); // 10
ptr++; // 移动到下一个int位置(地址+4,因为一个int类型数据占用4字节)
printf("%d\n", *ptr); // 20
3.2 指针比较
int *p1 = &arr[2];
int *p2 = &arr[4];
if(p1 < p2) { // 比较地址值,显然p2的地址值更大,此时若用p2-p1,值为2。
printf("p1在内存中的位置更靠前");
}
4.1 数组遍历
int nums[3] = {100,200,300};
int *p = nums; //此时指针p指向数组首地址
for(int i=0; i<3; i++){
printf("%d ", *(p+i)); // 100 200 300。(不断移动指针p在数组中指向的地址)
}
4.2 数组名即指针
printf("%p\n", nums); // 输出数组首地址。数组名称等于数组首元素的地址
printf("%d\n", nums[0]); // 等价于*(nums+0)
5.1 二级指针示例
int value = 50;
int *p1 = &value;
int **p2 = &p1; // 指向指针的指针
printf("%d", **p2); // 输出50
6.1 指针参数实现值修改(重点)
void add(int *num) {
*num += 10;
}
int main() {
int x = 5;
add(&x);
printf("%d", x); // 输出15
return 0;
}
6.2 返回指针的函数
int* findMax(int *a, int *b) {
return (*a > *b) ? a : b;
}
7.1 野指针示例
int *danger; // 未初始化
printf("%d", *danger); // 危险操作!可能崩溃,因为未初始化,指针不知道指向哪的地址
7.2 内存泄漏
int *p = malloc(sizeof(int));
*p = 10;
// 忘记free(p) → 内存泄漏
8.1 动态内存分配
int *arr = malloc(5 * sizeof(int));
for(int i=0; i<5; i++){
arr[i] = i*10;
}
free(arr); // 必须释放
8.2 函数指针
int add(int a, int b) { return a+b; }
int (*funcPtr)(int, int) = add;
printf("%d", funcPtr(3,5)); // 输出8