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

How to determine if two pointers point to the same block of memory

本文关键字:内存 是否 指针 何确定 两个      更新时间:2023-10-16

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

/*
 * 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;如何帮助解决问题?

行:

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

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

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.将指针指向int并进行算术运算通常是非常糟糕的做法。实际大小是由这些基元类型定义的,例如,它在指针或int不是32位的每个体系结构上都会中断。

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

例如:

#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: %dn", a, b, withinSameBlock(a, b));
  printf ("%p, %p: %dn", a, c, withinSameBlock(a, c));
  return 0;
}

首先,我们需要清楚的是,代码只适用于指针为32位、int也是32位的系统。在64位系统上,代码会失败得很惨。

左移位CCD_ 5设置CCD_ 6的最高有效位。换句话说,线

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指向相同的存储器块。

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

(1 << 31) >> 25会给你一个看起来像这样的位掩码:

11111111111111111111111111000000

a=ptr1b=ptr2ab设置为等于作为存储器地址的指针的值。temp与这些地址中的每一个(即a&tempb&temp(的逐位AND将屏蔽由ab保持的地址的最后6位。如果剩下的26位是相同的,那么原始地址必须在64字节内。

演示代码:

#include <stdio.h>
void main()
{
    int temp = (1 << 31) >> 25;
    printf("temp=%xn",temp);
    int p=5, q=6;
    int *ptr1=&p, *ptr2=&q;
    printf("*ptr1=%x, *ptr2=%xn",ptr1, ptr2);
    int a = ptr1;
    int b = ptr2;
    printf("a=%x, b=%xn",a,b);
    if ((a & temp) == (b & temp)) printf("truen");
    else printf("falsen");
}