一、核心概念
指针运算是指针对内存地址进行算术运算或关系运算的操作,核心围绕地址的移动和比较。
- 算术运算:加减整数、自增/自减(++, –)、指针相减。
- 关系运算:比较指针大小(>, <, ==等)。
二、核心知识点
- 算术运算步长:指针加减整数n时,实际移动的字节数为 n * sizeof(数据类型)。
- int *ptr + 1 → 移动4字节(假设int为4字节)
- char *ptr + 1 → 移动1字节
- 指针相减的意义:得到两个指针之间的元素个数,而非字节数。
int *p1 = &arr[2], *p2 = &arr[5]; int n = p2 – p1; // n = 3(相差3个元素)
- 关系运算规则:比较的是指针指向的地址高低,常用于数组或同一内存块。
- 数组与指针的等价性:数组名可视为指向首元素的指针,arr[i]等价于*(arr + i)。
- void指针的限制:void*指针不能直接运算(因步长未知),需转换为具体类型后再操作。
三、如何简单理解?
类比书本页码:
- 指针变量 → 当前页码(如第100页)
- 指针+1 → 翻到下一页(页数根据内容大小决定)
- 若每页存1个数字(int):翻过4页(4字节)
- 若每页存1个字母(char):翻过1页(1字节)
四、记忆口诀
“类型决定步长,加减元素数量;相减得元素差,比较看地址高低。”
五、代码示例及逐行解析
#include <stdio.h> int main() { int arr[] = {10, 20, 30, 40, 50}; // 定义一个包含5个整数的数组 int *ptr = arr; // ptr指向数组首元素(arr[0]) int sum = 0; // 初始化累加器 for (int i = 0; i < 5; i++) { sum += *ptr; // 取出ptr指向的值(如arr[0]的值10),累加到sum ptr++; // ptr移动至下一个元素(地址增加sizeof(int)=4字节) } printf(“Sum: %d\n”, sum); // 输出结果:Sum: 150 return 0; }
逐行解释:
- #include 引入标准输入输出库,使printf可用。
- int arr[] = {10, 20, 30, 40, 50};定义数组arr,包含5个整数,内存连续分配。
- int *ptr = arr;arr作为数组名,自动转换为指向首元素arr[0]的指针,赋值给ptr。
- int sum = 0;初始化变量sum,用于存储累加结果。
- for (int i = 0; i < 5; i++)循环5次,遍历数组所有元素。
- sum += *ptr;*ptr解引用指针,获取当前指向的元素值(如第一次循环时为10)。
- ptr++;指针自增,移动到下一个元素。由于ptr是int*类型,实际地址增加4字节(sizeof(int))。
- printf(“Sum: %d\n”, sum);输出累加结果:10 + 20 + 30 + 40 + 50 = 150。
六、常见问题
- 越界访问:若指针移动到数组之外(如ptr++超过5次),可能导致未定义行为。
- 类型匹配:不同指针类型(如int*和char*)运算步长不同,混用易出错。
- void指针运算:
void *p = arr; // p++; // 错误!void指针不能直接运算 int *q = (int*)p; q++; // 正确
总结:指针运算是C语言高效操作内存的核心,理解类型决定步长、数组与指针的关系后,便能灵活应用于遍历、偏移计算等场景。
