**核心原则:** 指针运算是**类型感知**的,它基于所指向**数据类型的大小 sizeof)** 进行。

---

#### 1. **指针 + 整数 / 指针 - 整数 p + N, p - N)**

* **目的:** 在连续内存(如数组)中,将指针向前或向后移动 N 个**元素**。

* **计算方式:**

p + N 的实际地址变化p 的地址 + N sizeof(*p))

p - N 的实际地址变化p 的地址 - N sizeof(*p))

* **结果类型:** 依然是同类型的指针。

* **示例:**

```c

int arr[] = {10, 20, 30};

int *p = &arr[0]; // p 指向 10

p = p + 1; // p 现在指向 20 (地址增加了 sizeof(int) 字节)

p = p - 2; // p 现在指向 10 (地址减少了 2 * sizeof(int) 字节)

```

* **注意:** 必须确保指针移动后仍然指向有效内存(通常在数组或已分配内存块内及紧邻其后)。超出范围会导致**未定义行为 (Undefined Behavior, UB)**。

---

#### 2. **指针相减 p1 - p2)**

* **目的:** 计算两个指针之间相隔了多少个**元素**。

* **计算方式:** (p1 的地址 - p2 的地址) / sizeof(公共类型)

* **结果类型:** ptrdiff_t (一个有符号整数类型,定义在 <stddef.h>)。

* **重要限制:**

两个指针必须*指向相同类型的数据**。

两个指针必须都指向*同一个数组**(或连续内存块)中的元素,或者指向该数组末尾的下一个位置。

否则,结果是*未定义行为 (UB)**。

* **示例:**

```c

int arr[] = {10, 20, 30, 40};

int *p1 = &arr[1]; // 指向 20

int *p2 = &arr[3]; // 指向 40

ptrdiff_t diff = p2 - p1; // diff = 2 (表示相隔 2 个 int 元素)

```

---

#### 3. **指针相加 p1 + p2)**

* **C语言规定:** **不允许** 指针相加。

* **原因:** 两个内存地址相加没有明确的、有意义的语义。

* **结果:** 编译错误。

---

#### 4. *void 指针的运算*

* **C90 标准:** 不允许对 void * 指针进行算术运算p+N)。

* **C99 及更高标准:** 允许对 void 指针的算术运算,其行为等同于 char ,即每次移动**一个字节**。

* **推荐做法:** 为了代码的清晰性和跨编译器兼容性,在对 void 指针进行算术运算前,最好将其*显式地强制转换 (cast)** 为 char unsigned char

```c

void *ptr = some_address;

ptr = (char *)ptr + 10; // 移动 10 个字节

```

---

#### 5. **不同类型指针的运算**

* **与整数加减:**

int p_int; p_int + 1; 移动 sizeof(int) 字节。

char p_char; p_char + 1; 移动 sizeof(char) (即 1) 字节。

* 各自按其类型规则运算。

* **相减:**

直接对不同类型的指针相减 (如 (int)p - (char*)q) 通常是**未定义行为 (UB)**,即使编译器可能允许。

* **获取字节差:** 如果需要计算任意两个指针之间相隔的**字节数**,应将两者都强制转换为 char (或 unsigned char ) 后再相减。

```c

int i_val;

double d_val;

char ptr1 = (char )&i_val;

char ptr2 = (char )&d_val;

ptrdiff_t byte_diff = ptr2 - ptr1; // 获取两者间的字节数

```

* **赋值:** 不同类型的指针可以直接赋值,但通常伴随着隐式或显式类型转换,可能会有数据丢失风险或需要注意对齐。

---

#### **总结表格**

| 运算类型 | 参与者 | 结果类型 | 作用 | 关键限制 / 注意点 |

| :--------------- | :---------------------- | :--------------- | :---------------------------- | :------------------------------------------------------- |

| p + N / p - N| 指针 p,整数 N | 指针 | 移动 N 个**元素** | 移动量 = N sizeof(p);需在有效内存范围 |

| p1 - p2 | 指针 p1,指针 p2 | ptrdiff_t | 计算相隔的**元素数量** | 必须同类型,指向同一数组;否则 UB |

| p1 + p2 | 指针 p1,指针 p2 | **不允许** | **无意义,编译错误** | C语言标准禁止 |

| void + N | void p,整数 N | void | C99+ 标准下,移动 N*字节** | 推荐强制转换为 char unsigned char 进行操作 |

| 不同类型指针相减 | p1, p2 (不同类型) | **UB / 需转换** | 获取字节差需先转为 char | (char)p1 - (char*)p2 可得字节差 |

---