编程C 开发人员

描述 C 语言中指针比较操作的差异。指针比较的规则是什么,何时这种比较是正确的,开发者可能面临哪些陷阱?

用 Hintsage AI 助手通过面试

答案。

问题历史: 在 C 语言中,指针是存储其他对象地址的变量。出现了一个问题:如何比较这样的值,因为内存可能以最不可预测的方式分配。语言允许指针之间的比较操作,但施加了一系列限制,以确保行为保持确定性。

问题: 只有相同数组的元素或同一对象的指针之间的比较是正确的。指向不相关对象(不同变量或未包含在同一数组中的分配内存区域)的指针比较是未定义行为(undefined behavior)。

解决方案: 应避免比较指向不相关内存区域的指针,只在同一数组/字符串/缓冲区内使用,并且与 NULL 的比较是安全的。

代码示例:

#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int *p1 = &arr[1]; int *p2 = &arr[3]; if (p1 < p2) { printf("p1 指向的数组元素早于 p2 指向的元素\n"); } }

关键特点:

  • 指针比较的正确性取决于它们是否属于同一对象。
  • 与 NULL 的比较始终是安全的,并用于验证有效性。
  • 指向不同对象的指针比较会导致未定义行为。

带陷阱的问题。

1. 可以比较通过 malloc 获取的指针,它们指向不同的内存块吗?

不可以,比较这样的指针是不允许的——标准未定义其行为。仅允许比较指向同一分配内存块的指针或与 NULL。

2. 如果 int 和 double 类型的指针指向不同变量但具有相同的数值,比较返回什么?**

只在两个指针被转换为相同类型并指向同一对象的情况下,比较才是可能的。如果不符合该条件,结果是未定义的——地址值可能相同,但标准并不保证这种行为。

3. 将指向数组第一个元素的指针与指向其结尾的指针(例如,arr 和 arr + N)进行比较是否正确?

是的,这是正确的。arr + N 指向的是 imaginary 元素,位于最后一个元素之后,编译器保证 arr <= arr + N。

常见错误和反模式

  • 指向不同对象的指针比较
  • 在不考虑数组隶属关系的情况下分析指针顺序
  • 使用比较结果在不相关区域间组织逻辑

生活中的一个例子

一名员工决定实现一个地址比较函数,以确定两种从不同内存块分配的结构"哪个先创建"。

优点:

  • 代码在他的计算机上工作

缺点:

  • 在其他架构上,一些指针可能小于其他指针,代码结果变得不可预测,错误偶尔且随机出现。

经过审查后,实现了通过将所有结构分配到同一缓冲区并在允许范围内进行比较来检查指针是否属于同一内存块。

优点:

  • 程序变得可移植
  • 明确反映了仅"自己的"比较限制

缺点:

  • 存储结构的复杂性略有增加