如果我有一个数组和一个大小,并且我想检查给定指针是否指向数组内的元素,那么在没有调用UB的情况下,有没有办法在标准C或C ++中这样做?
这有用吗?
bool is_inside(someType * array, int size, someType * other_pointer){
for (int i = 0; i < size; i++)
if (array + i == other_pointer)
return true;
return false;
}
编辑:我的理解是,除了==
和!=
之外,你不能使用不指向同一个数组而没有UB的指针(尽管在实践中它按预期工作)。我错了吗?
答案 0 :(得分:3)
保证数组在内存中是连续的,所以只需检查指针是否在第一个元素和最后一个元素的地址范围内。
答案 1 :(得分:2)
bool is_inside(someType * array, int size, someType * other_pointer) {
return array <= other_pointer && other_pointer < array + size;
}
答案 2 :(得分:1)
您的解决方案可行,但不是最佳,因为它包含不必要的循环。
你应该做的是获取指向数组的指针,数组大小(以字节为单位),并检查指向的地址是否落在该数组占用的地址空间内。
答案 3 :(得分:1)
您可以简单地写一下:
bool inside = (other_pointer >= array) && (other_pointer < array+size);
这是合法检查。
答案 4 :(得分:1)
这取决于你对UB的意思。
具体来说,对于指针比较,C ++标准的第5.9节“关系运算符”说:
如果同一类型的两个指针p和q指向不同的对象 不是同一个对象或不同功能的成员,或者只是其中一个 它们为空,
p<q
,p>q
,p<=q
和p>=q
的结果未指定。
请注意,行为是未指定(意味着比较的结果可能是true
或false
- 换句话说,结果并不能告诉您任何有用的信息 - 但是实现不需要指定哪个)而不是 undefined (意味着编译器或生成的程序可以做任何事情)。
然而,到目前为止,我只看到一系列的实现没有使用像Kirill这样的代码执行预期的操作:
bool inside = (other_pointer >= array) && (other_pointer < array+size);
这些实现是用于构建MS-DOS实模式程序的编译器,其中地址具有段落和偏移部分。地址FF00:0010和FF01:0000指向相同的内存位置,但如果我没记错,编译器不能保证以预期的方式运行,除非编译某些内存模型(当然 HUGE 模型,但也许是其他人。)
但是,如果p
或q
没有指向现有对象(因为例如指针被释放),那么无论你做什么,行为都将是不确定的。因此,您无法使用这种方法来确定指针是否仍然有效。