:内存、地址与指针运算)
1. 内存和地址程序运行时数据存储在内存中。内存可以看作一个连续的字节序列每个字节都有一个唯一的编号这个编号就是内存地址。地址从 0 开始递增操作系统通过地址来定位和访问内存中的数据。在 C 语言中变量在定义时会向内存申请一块空间这块空间的大小由变量的类型决定。例如int类型通常占用 4 个字节char类型占用 1 个字节。变量所占内存空间的首字节地址就是该变量的地址。#include stdio.h int main() { int a 10; printf(变量 a 的值%d\n, a); printf(变量 a 的地址%p\n, a); return 0; }上面的代码中a用于取出变量a的地址%p是打印地址的格式说明符。运行结果会显示类似0x7ffd8f3a2b4c的十六进制地址。2. 指针变量和地址指针变量是专门用来存放地址的变量。通过指针我们可以间接访问和修改它所指向的变量。定义指针变量的语法为类型 * 变量名。例如int *p表示p是一个指向int类型数据的指针变量。#include stdio.h int main() { int a 10; int *p a; // p 存放变量 a 的地址 printf(a 的值%d\n, a); printf(p 中存放的地址%p\n, p); printf(通过 p 访问 a 的值%d\n, *p); *p 20; // 通过指针修改 a 的值 printf(修改后 a 的值%d\n, a); return 0; }这里有两个关键运算符取地址运算符取出变量的地址。解引用运算符*通过地址访问该地址上存储的数据。当执行*p 20时程序会找到p中存放的地址并往这个地址写入 20因此变量a的值被修改为 20。3. 指针变量类型的意义指针变量本身存放的是地址无论指向什么类型指针变量所占的内存大小通常是相同的在 64 位系统上为 8 字节。那么为什么指针还要区分类型呢指针的类型决定了两个重要信息解引用时访问的字节数int *解引用时读取 4 个字节char *解引用时只读取 1 个字节。指针加减运算时的步长int *加 1 跳过 4 个字节char *加 1 只跳过 1 个字节。#include stdio.h int main() { int a 0x12345678; int *p a; char *c (char *)a; printf(int 指针解引用%x\n, *p); printf(char 指针解引用%x\n, *c); printf(int 指针加 1 的地址%p\n, p 1); printf(char 指针加 1 的地址%p\n, c 1); return 0; }运行结果中p 1比p大 4 个字节而c 1比c大 1 个字节。这说明指针类型决定了指针运算的步长也决定了解引用时能访问的数据范围。4. 指针运算指针运算主要包括以下几种指针加整数p n表示向后移动n个同类型元素。指针减整数p - n表示向前移动n个同类型元素。指针减指针p1 - p2表示两个指针之间相隔的元素个数。指针比较可以用关系运算符比较两个指针指向的地址大小。指针运算在遍历数组时非常常用。下面通过一个数组遍历的例子来演示#include stdio.h int main() { int arr[] {10, 20, 30, 40, 50}; int *p arr; // 数组名就是首元素地址 for (int i 0; i 5; i) { printf(arr[%d] %d地址%p\n, i, *(p i), p i); } // 指针减指针计算元素个数 int *start arr[0]; int *end arr[4]; printf(相隔元素个数%ld\n, end - start); return 0; }在这个例子中*(p i)等价于arr[i]p i指向数组第i个元素。而end - start的结果是 4表示两个指针之间相隔 4 个元素。需要注意的是指针运算必须限定在同一个数组或同一块连续内存范围内否则结果是未定义的容易引发难以排查的错误。5. 小结本文介绍了指针的基础知识内存地址是数据在内存中的唯一编号指针变量用于存放地址指针类型决定了解引用范围和运算步长指针运算则提供了灵活访问连续内存的手段。理解这些概念是后续学习数组、字符串、函数指针和动态内存管理的基础。