【问题标题】:Comparing pointer values after conversion, still same equality?转换后比较指针值,仍然相同吗?
【发布时间】:2016-05-22 19:44:06
【问题描述】:

在探索将指针转换为字符串时,intptr_tuintptr_t 之类的

void *p;
char sp[100];
snprintf(sp, sizeof sp, "%p, p);
intptr_t ip = (intptr_t) p;

我想知道 2 个指针 some_type *a; some_type *b; 和它们的相等性在转换时如何转移。


案例 1:两个指针指向相同位置(对象、对象内的偏移量、1-过去、函数、数组)但具有不同的位模式,或者是 2 个具有不同位模式的空指针位模式。这种情况很难在某些平台上创建,如果有的话。

当然,它们作为指针比较相等(C11 §6.5.9 6)。然而,作为字符串,intptr_tuintptr_t,我期望它们是不同的,但 认为相同是可以的。

Q1 案例 1 指针转换(转换为字符串、intptr_tuintptr_t)相同或不同 - 是否都符合结果?

情况 2(常见情况):所有其他指针对混合但不是情况 1:空值、对象、对象内、1-过去对象、函数...中的任何一个

Q2 Case 2 指针a,b:必须a == b 转换为字符串,intptr_tuintptr_t 有相同的结果(使用!strcmp()====)?


使用"%p" 打印指针可能不恰当地称为“转换”,但希望仍能传达这个想法。


测试代码以尝试一些可能性。

void ptr_compare(void *pa, void *pb, 
    bool *pcmp, bool *mcmp, bool *scmp, bool *icmp, bool *ucmp) {

  // pointer compare
  *pcmp = pa == pb;

  // memory compare
  *mcmp = memcmp(&pa, &pb, sizeof pa) == 0;

  // string compare
  char sa[100];
  snprintf(sa, sizeof sa, "%p", pa);
  char sb[100];
  snprintf(sb, sizeof sb, "%p", pb);
  *scmp = !strcmp(sa, sb);

  // signed compare
  intptr_t ia = (intptr_t) pa;
  intptr_t ib = (intptr_t) pb;
  *icmp = ia == ib;

  // unsigned compare
  uintptr_t ua = (uintptr_t) pa;
  uintptr_t ub = (uintptr_t) pb;
  *ucmp = ua == ub;
}

void ptr_test(void *pa, void *pb) {
  bool pcmp, mcmp, scmp, icmp, ucmp;
  ptr_compare(pa, pb, &pcmp, &mcmp, &scmp, &icmp, &ucmp);

  // If same bit pattern ...
  if (mcmp) {
    if (pcmp && scmp && icmp && ucmp) return;
  // else different bit pattern ...
  } else {
    if (!pcmp && !scmp && !icmp && !ucmp) return;
  }

  // Something interesting !
  printf("ptra:%p ptrb:%p --> pcmp:%d mcmp:%d scmp:%d icmp:%d ucmp:%d\n", pa,
      pb, pcmp, mcmp, scmp, icmp, ucmp);
}

int main(void) {
  char p[1];
  void *ptrs[] = { 0, NULL, "123", "123", "456", p, p, main };
  for (size_t ia = 0; ia < sizeof ptrs / sizeof ptrs[0]; ia++) {
    for (size_t ib = 0; ib < sizeof ptrs / sizeof ptrs[0]; ib++) {
      ptr_test(ptrs[ia], ptrs[ib]);
    }
  }
  puts("Done");
  return 0;
}

结果。在两个经过测试的平台上,我显然无法创建“有趣的东西!”

Done

【问题讨论】:

    标签: c pointers language-lawyer


    【解决方案1】:

    指针的底层值取决于实现。然而在像 X86 这样的系统上,指针不会因为你将它转换为不同的类型而改变值。类型是编译时信息,它指向的地址是运行时。类型会影响编译器生成的代码,以便对其进行推理和执行数学运算。

    【讨论】:

    • "但是在像 X86 这样的系统上,指针不会因为你将它转换为不同的类型而改变值" --> 当然这很常见,尤其是对于平面架构,但是在分段(x86 )、哈佛或未来的架构,这可能不是真的。我没有在 C 标准中找到“不会改变值”。 C 将指针指定为与整数不同的组 - 无法比较值,除非您可以将其放入另一个。当将带有 (intptr_t) 的指针转换为整数时,位模式当然可以改变。 Example answer 可能会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多