前言:
上一期我们分享了C语言中的程序结构,本篇我们来介绍C语言中指针的基础知识。
Part 1:理解内存与地址:
1. 什么是内存?
内存就像一栋巨大的写字楼,每个房间(内存单元)都有一个门牌号(地址),房间内可以存放数据(如数字、字符等)。
每个房间的大小固定(例如1字节),不同类型的数据需要不同数量的房间(如
int占4字节,char占1字节)。
2. 变量如何存储?
当声明变量
int a = 10;,相当于:在写字楼中预订一个连续的房间(4个字节)。
给这些房间贴上标签“a”。
将值
10存入这些房间。
变量的地址就是这些房间的“起始门牌号”。
Part 2:指针的本质
1. 指针是什么?
指针是一个变量,但它存储的不是普通数据,而是另一个变量的地址。
比喻:指针就像一张“小纸条”,上面写着某个房间的门牌号(地址),而不是房间里的物品(数据)。
2. 指针的声明与初始化
int a = 10; // 普通变量
int *p = &a; // 指针变量p,存储a的地址我们看上面的例子,int *p:p是一个指向int类型的指针。其中&a是取地址运算符,是用来获取变量a的地址。
3. 指针的“解引用”(*操作符)
printf("%d", *p); // 输出10(通过p找到a的值)
*p = 20; // 通过p修改a的值为20上面的例子中,*p的含义和作用是根据指针p中存储的地址找到其在内存对应的位置并进行操作。
Part 3:指针的常见用法
示例1:指针与变量:
为了更好的理解指针和内存地址对应的关系,我们可以用画图或者表格的形式来展示,方便我们理解。
int a = 10; // 假设a的地址是0x1000
int *p = &a; // p的值是0x1000
还用上述的示例,那再内存中,图示大概是这个样子:

示例2:修改指针指向的值
int a = 10, b = 20;
int *p = &a; // p指向a
p = &b; // 现在p指向b
*p = 30; // 修改b的值为30这个例子中,我们可以详细的看下内存的变化过程,我逐步拆解分析下,
初始状态:
a的值为10,地址假设为0x1000。b的值为20,地址假设为0x2000。指针
p初始化为&a(即0x1000)。
内存地址图如下:

执行 p = &b:
p的值变为0x2000(即b的地址)。此时内存地址变化如下

执行 *p = 30:
通过
p修改b的值为30。

最终结果
a的值保持为10(未被修改)。b的值变为30(通过指针修改)。
Part 4:指针的常见用途(分场景详解)
场景1:函数参数传递(修改实参)
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main() {
int a = 1, b = 2;
swap(&a, &b); // 传递地址
printf("a=%d, b=%d", a, b); // 输出a=2, b=1
return 0;
}- Tips:如果不传指针,函数内部无法修改外部的变量。
场景2:动态内存分配
int *arr = (int*)malloc(5 * sizeof(int)); // 申请5个int的空间
if (arr != NULL) {
for (int i = 0; i < 5; i++) {
arr[i] = i * 10; // 通过指针操作数组
}
free(arr); // 必须手动释放内存!
}- Tips:传统数组大小固定,动态分配允许程序运行时决定内存大小。
Part 5:指针的常见陷阱以及问题
1. 空指针(NULL Pointer)
int *p = NULL; // 明确初始化为空
if (p != NULL) {
*p = 10; // 安全操作
}2. 野指针(Dangling Pointer)
int *p;
{
int a = 10;
p = &a; // p指向局部变量a
} // a的作用域结束,内存被释放
*p = 20; // 危险!操作已释放的内存3. 指针类型不匹配
double d = 3.14;
int *p = &d; // 错误!类型不匹配4. 指针可以进行运算操作
a. 指针的加减
int arr[3] = {10, 20, 30};
int *p = arr;
p++; // p指向arr[1]
p--; // p回到arr[0]
p += 2; // p指向arr[2]Tips:p + n 的实际地址是 p + n * sizeof(数据类型)
b. 指针比较
int *p1 = &arr[0];
int *p2 = &arr[2];
if (p1 < p2) { // 比较地址大小
printf("p1在p2之前");
}示例3:指针的综合应用示例
#include <stdio.h>
#include <stdlib.h>
int main() {
// 基础指针操作
int num = 42;
int *p = #
printf("num的值: %d, 地址: %p\n", num, &num);
printf("p存储的地址: %p, 通过p访问的值: %d\n", p, *p);
// 动态内存分配
int *dynamicArr = (int*)malloc(3 * sizeof(int));
if (dynamicArr != NULL) {
dynamicArr[0] = 10;
*(dynamicArr + 1) = 20; // 等价于dynamicArr[1] = 20
dynamicArr[2] = 30;
for (int i = 0; i < 3; i++) {
printf("dynamicArr[%d] = %d\n", i, dynamicArr[i]);
}
free(dynamicArr);
}
// 指针与函数
void addTen(int *x) {
*x += 10;
}
int value = 5;
addTen(&value);
printf("addTen后的值: %d\n", value); // 输出15
return 0;
}这个例子感兴趣的朋友可以自己玩一下试试,最后的输出结果如下:
num的值: 42, 地址: 0x7ffd1234abcd
p存储的地址: 0x7ffd1234abcd, 通过p访问的值: 42
dynamicArr[0] = 10
dynamicArr[1] = 20
dynamicArr[2] = 30
addTen后的值: 15最后:
虽然是慢工但是不是什么细活 我们下期见。




