如何确定两个指针是否指向同一块内存

时间:2014-07-19 04:09:58

标签: c++ c

我正在尝试解决以下问题:

/*
 * Return 1 if ptr1 and ptr2 are within the *same* 64-byte aligned
 * block (or word) of memory. Return zero otherwise.
 *
 * Operators / and % and loops are NOT allowed.
 */
/*

我有以下代码:

int withinSameBlock(int * ptr1, int * ptr2) {
  // TODO
  int temp = (1 << 31) >> 25;
  int a = ptr1;
  int b = ptr2;
  return (a & temp) == (b & temp);
}

我被告知这正确地解决了这个问题,但我不确定它是如何工作的。具体来说,行int temp = (1 << 31) >> 25;如何帮助解决问题?

4 个答案:

答案 0 :(得分:4)

该行:

int temp = (1 << 31) >> 25;

不正确或触发未定义的行为(取决于wordsize)。只是碰巧机器上的未定义行为和编译器做了正确的事情 而恰好给出了正确的答案。为了避免未定义的行为并使代码更清晰,您应该使用:

int withinSameBlock(int * ptr1, int * ptr2) {
    uintptr_t temp = ~(uintptr_t)63;
    uintptr_t a = (uintptr_t)ptr1;
    uintptr_t b = (uintptr_t)ptr2;
    return (a & temp) == (b & temp);
}

答案 1 :(得分:3)

我不确定你在哪里获得该代码(作业?)但这太可怕了。 1.铸造指向int和做算术的指针一般是非常糟糕的做法。实际大小未被这些原始类型定义,为了即时,它在指针或int不是32位的每个架构上都会中断。

你应该使用uintptr_t,它通常大于或等于指针的大小(除了ambigous spec允许的理论拱形)

例如:

#include <stdint.h>
#include <stdio.h>

int withinSameBlock(int * ptr1, int * ptr2) {
  uintptr_t p1 = reinterpret_cast<uintptr_t>(ptr1);
  uintptr_t p2 = reinterpret_cast<uintptr_t>(ptr2);
  uintptr_t mask = ~ (uintptr_t)0x3F;
  return (p1 & mask) == (p2 & mask);
}


int main() {
  int* a = (int*) 0xdeadbeef;
  int* b = (int*) 0xdeadbeee;
  int* c = (int*) 0xdeadc0de;
  printf ("%p, %p: %d\n", a, b, withinSameBlock(a, b));
  printf ("%p, %p: %d\n", a, c, withinSameBlock(a, c));
  return 0;
}

答案 2 :(得分:2)

首先,我们需要明确的是,代码仅适用于指针为32位且int也为32位的系统。在64位系统上,代码将失败。

左移(1 << 31)设置int的最重要位。换句话说,行

int temp = (1 << 31);

相同
int temp = 0x80000000;

由于int是有符号数,因此最高有效位是符号位。向右移动带符号的数字将符号位复制为低位。因此向右移动25次会产生一个在高26位中具有1的值。换句话说,行

int temp = (1 << 31) >> 25;

与(如果写成的话会更清楚)相同(

int temp = 0xffffffc0;

该行

return (a & temp) == (b & temp);

比较ab的高26位,忽略低6位。如果高位匹配,则ab指向同一块内存。

答案 3 :(得分:1)

假设有32位指针,如果两个指针位于同一个64字节的内存块中,那么它们的地址只会在6个最低有效位中发生变化。

(1 << 31) >> 25会给你一个如下所示的位掩码:

11111111111111111111111111000000

a=ptr1b=ptr2ab设置为等于指针的值,即指针的内存地址。 temp与其中每一个(即a&tempb&temp)的按位AND将屏蔽a和{{1}所拥有的地址的最后6位}。如果剩余的26位相同,那么原始地址必须彼此相差64个字节。

演示代码:

b