检查指针是否指向数组

时间:2011-01-11 13:14:42

标签: c++ arrays pointers comparison

我可以检查给定指针是否指向数组中的对象,由其边界指定?

template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
    return begin <= p && p < end;
}

如果p指向数组范围之外,指针比较是否会调用未定义的行为?在那种情况下,我该如何解决这个问题?它是否适用于void指针?还是不可能解决?

6 个答案:

答案 0 :(得分:10)

虽然比较仅对数组中的指针和“一个结束”之间的指针有效,但使用带有指针的集合或映射作为键是有效的,它使用std::less<T*>

1996年在comp.std.c++

上就这种方式进行了大量讨论

答案 1 :(得分:7)

直接来自MSDN documentation

  

除非:

,否则无法比较两种不同类型的指针      
      
  • 一种类型是从另一种类型派生的类类型。
  •   
  • 至少有一个指针被显式转换(强制转换)为void *类型。 (另一个指针隐式转换为转换类型void *。)
  •   

因此void*可以与其他任何内容进行比较(包括另一个void*)。但这种比较会产生有意义的结果吗?

  

如果两个指针指向的元素   相同的数组或元素之一   超出阵列的最后,   用更高的指针指向对象   下标比较高。对照   指针只保证有效   当指针引用中的对象时   相同的数组或位置   超过阵列结束。

看起来不是。如果您已经知道您正在比较数组中的项目(或刚刚超过它),那么比较不能保证有意义。

然而,有一个解决方案:STL提供std::less<>std::greater<>,它将适用于任何指针类型,并将在所有情况下生成有效结果:

if (std::less<T*>()(p, begin)) {
    // p is out of bounds
}

<强>更新

this question的答案给出了相同的建议(std::less)并引用了标准。

答案 2 :(得分:5)

C ++标准没有规定在将指针与不在同一数组中的对象进行比较时会发生什么,因此未定义的行为。但是,C ++标准并不是您的平台必须符合的唯一标准。像POSIX这样的其他标准指定了C ++标准留下的未定义行为。 在具有Linux和Win32 / 64等虚拟地址空间的平台上,您可以比较任何指针而不会导致任何未定义的行为。

答案 3 :(得分:5)

这样做的唯一正确方法是这样的方法。

template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
    for (; begin != end; ++begin)
    {
        if (p == begin)
            return true;
    }
    return false;
}

显然,如果T == void,这不起作用。我不确定两个void*是否在技术上定义了一个范围。当然,如果你有Derived[n],那么说(Base*)Derived, (Base*)(Derived + n)定义了一个有效范围是不正确的,所以我看不到用指向实际数组元素的指针以外的任何东西来定义范围是有效的。类型。

下面的方法失败,因为如果两个操作数不指向同一对象的成员或同一数组的元素,则未指定<返回的内容。 (5.9 [expr.rel] / 2)

template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
    return !(p < begin) && (p < end);
}

下面的方法失败了,因为如果两个操作数没有指向同一个对象的成员或同一个数组的元素,那么std::less<T*>::operator()返回的内容也是未指定的。

确实,std::less必须专门用于任何指针类型,如果内置<没有,则产生总订单,但这仅对诸如提供密钥等用途有用setmap。不能保证总顺序不会将不同的数组或对象交错在一起。

例如,在分段存储器架构上,对象偏移可以用于<,并且作为std::less<T*>的最重要的区分因素,其中段索引用于断开关系。在这样的系统中,可以在第二个不同数组的边界之间对一个数组的元素进行排序。

template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
    return !(std::less<T*>()(p, begin)) && (std::less<T*>()(p, end));
}

答案 4 :(得分:1)

指针类型的比较不一定会导致总订单。但是,std :: less / std :: greater_equal会这样做。所以...

template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
    return std::greater_equal<T*>()(p, begin) && std::less<T*>()(p, end);
}

会奏效。

答案 5 :(得分:0)

您是否可以使用std::distance执行此操作,即您的问题可以归结为:

return distance(begin, p) >= 0 && distance(begin, p) < distance(begin, end);

鉴于这个随机访问迭代器(指针)正在传入,它应该归结为一些指针算术而不是指针比较? (我假设结束真的是结束而不是数组中的最后一项,如果最后一项改为小于<=)。

我可能会离开标记......

相关问题