[英]How to check whether a pointer is pointing to an element inside an array?
以下函數旨在檢查指針b
是否指向數組a[0],...,a[len-1]
?
bool between(int *a, int len, int *b)
{
return (a <= b) && (b < a + len);
}
通過閱讀https://en.cppreference.com/w/c/language/operator_comparison,該函數調用未定義的行為。 如果是這樣,這樣做的正確方法是什么? 為什么標准不允許這樣做?
使用比較運算符<
, <=
, >
和>=
比較兩個不相關的指針(即不指向同一數組對象或結構的成員的指針)確實調用鏈接頁面中描述的未定義行為以及C標准第6.5.8節。
至於為什么不允許這樣做,並非所有實現都具有平坦的存儲器模型,並且不相關的對象不需要駐留在執行比較的存儲器區域中。
所以,你的函數將返回在案件真實b
點的成員a
,假當它指向一個過去的最后一個成員a
,和原本調用未定義的行為。
但是,允許使用==
或!=
來比較不相關的指針。 因此,您可以通過循環遍歷數組並使用相等運算符將目標指針與每個元素進行比較來規避比較運算符的限制:
bool between(int *a, int len, int *b)
{
int i;
for (i=0; i<len; i++) {
if (a+i == b) {
return true;
}
}
return false;
}
雖然這不是一個有效的遠程檢查,但它是唯一合規的方法。
當然,最好以這樣的方式構建程序,以便不需要這樣的比較。 允許指向數組內部的指針落在數組之外的程序已經在調用未定義的行為,因此修復它將不再需要這樣的函數。
然而,注意,它允許一個指針遞增到一個元件過去的陣列的端部和在該指針執行比較(盡管它不能被解除引用)。
除了@dbush很好的答案,代碼可以做陣列側數學a
,實現了更快的潛在積極的結果。
通過首先嘗試二進制搜索,如果between()
的結果為true
並且指向整數的映射在通用實現中,則true
值將在O(log(n))時間內找到。
如果通過二進制搜索在數組中找不到b
,則仍然需要線性來處理指針到整數的異常映射。
對於大型數組,例如n=1,000,000
,執行bsearch
的log2(1,000,000)步驟是無關緊要的。 對於小型陣列,最好直接進入循環。
// When optional, but common, uintptr_t available
int fcmp(const void *key, const void *array_element) {
if (key == array_element) {
return 0;
}
uintptr_t ai = (uintptr_t) array_element;
uintptr_t ki = (uintptr_t) key;
return (ai > ki) - (ai < ki);
}
// Best to use `size_t` for array indexing
bool between(int *a, size_t a_sz, int *b) {
if (bsearch(b, a, a_sz, sizeof *a, fcmp)) {
return true;
}
for (size_t i = 0; i < a_sz; i++) {
if (a + i == b) {
return true;
}
}
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.