【问题标题】:Check if pointer points to given array检查指针是否指向给定数组
【发布时间】:2016-10-30 03:27:51
【问题描述】:

所以我有一个函数,它返回一个指向数组 A 中元素的指针。我还有另一个函数,它将该指针作为参数。但是,我需要该函数能够处理它可能被传递一个完全任意指针的可能性。

有没有办法检测指针是否指向结构中的某个位置?在这种情况下,我的数组 A?

我见过类似的关于 C++ 的问题,但不是关于 C 的。

【问题讨论】:

  • 可能还有另一个问题在问这个问题。排序。标准并没有说它会起作用,但是如果你知道数组的开始、元素的数量和每个元素的大小,以及给定的指针,那么你就可以判断给定的指针是否落在数组的开始和结束。问题是,如果指针超出范围,则无法保证按标准进行比较,尽管现在大多数情况下,在非分段机器(大多数)上,它实际上确实有效。
  • 如果您正在处理数组,为什么不接收偏移量?我的意思是,一个简单的整数用作索引。这样您就可以节省检查物品的费用。

标签: c arrays pointers


【解决方案1】:

唯一可移植的方法是对指针的所有可能有效值使用相等测试。例如:

int A[10];

bool points_to_A(int *ptr)
{
    for (int i = 0; i < 10; ++i)
        if ( ptr == &A[i] )
             return true;

    return false;
}

请注意,对两个指针使用关系运算符(例如&lt;)或减法是未定义的行为,除非这两个指针确实指向同一个数组的元素(或最后一个)。

【讨论】:

  • 聪明!这样就消除了警告
  • int array[100000]; ... 哎哟!但这就是标准所说的有效。
  • 值得一提的是,除非两个指针来自同一个数组,或者除非在 C++ 中,否则减法指针(例如 ptr - A)也会产生未定义的行为。
  • @JonathanLeffler 似乎这应该是一个简单的编译器优化,尽管 gcc 和 clang 似乎都没有这样做,即使 intchar 取代
  • @qbolec 否,指针的== 运算符对于所有有效指针都是明确定义的
【解决方案2】:

在第 §6.5.8 节关系运算符中,C11 标准 (ISO/IEC 9899:2011) 说:

当比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。如果两个指向对象类型的指针都指向同一个对象,或者都指向同一个数组对象的最后一个元素,它们比较相等。如果指向的对象是同一个聚合对象的成员,则指向稍后声明的结构成员的指针比较大于指向结构中较早声明的成员的指针,并且指向具有较大下标值的数组元素的指针比较大于指向同一数组的元素的指针具有较低的下标值。所有指向同一联合对象成员的指针比较相等。如果表达式P指向一个数组对象的一个​​元素,而表达式Q指向同一个数组对象的最后一个元素,那么指针表达式Q+1比较大于 P。在所有其他情况下,行为是未定义的。

如果您知道指针在数组范围内,则比较起作用。如果指针超出范围,则无法确定比较是否有效。在实践中,它通常会这样做,但标准明确表示比较会产生未定义的行为。

请注意,对于数组SomeType array[20];,地址&amp;array[20] 保证有效,并且可以可靠地与从&amp;array[0]&amp;array[19] 的任何地址进行比较。您需要决定是否要将其计为在您的数组中。

如果观察到标准不保证它会起作用,那么,你可以比较两个int指针:

int within_int_array(int *array, size_t num_ints, int *ptr)
{
    return ptr >= array && ptr < array + num_ints;
}

如今,您应该对调用未定义的行为更加谨慎。编译器对使用未定义行为的程序做一些讨厌的事情,从技术上讲,你没有追索权,因为标准说“未定义行为”。

【讨论】:

  • 关于您之前关于大型 [~100000] 数组的评论:如果您需要经常针对数组进行测试,您不能将所有指向数组的有效指针转换为 uintptr_t 并构建一个哈希表.然后要找出指针p 是否指向数组的元素,您可以将p 转换为uintptr_t,对结果进行散列并检查表。或者这只是一个坏主意?
  • @DavidBowling:可以使用它(哈希表或类似的东西),但我不禁觉得知道你的指针指向哪里比需要这么多更好基础设施。
猜你喜欢
  • 2011-06-07
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 2013-08-20
相关资源
最近更新 更多