2

In exploring pointer conversions to a string, intptr_t and uintptr_t like

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

I wondered how 2 pointers some_type *a; some_type *b; and their equal-ness would transfer when converted.


Case 1: Two pointers point to the same place (object, offset within an object, 1-past, function, array) yet have different bit patterns, or are 2 null pointers that have different bit patterns. This case is hard to create on some platforms, if at all.

Certainly they compare equal as pointers (C11 §6.5.9 6). Yet as strings, intptr_t or uintptr_t, I expect them to be different, yet think being the same is OK.

Q1 Case 1 pointers convert (to string, intptr_t, uintptr_t) the same or different - are both results compliant?

Case 2 (the common situation): All other pointer pair mixes but not of case 1: any of null, object, within object, 1-past object, function, ...

Q2 Case 2 pointers a,b: Must a == b have the same result when converting to string, intptr_t, uintptr_t (using !strcmp(), ==, ==)?


Use "%p" to print a pointer might not be properly called "converting", but hopefully the idea is still conveyed.


Test code to exercise some possibilities.

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;
}

Results. On two tested platforms, I apparently cannot create "Something interesting !"

Done
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256

1 Answers1

0

The underlying value of pointers is implementation dependent. However on systems like X86, the pointer wouldn't change value just because you cast it to a different type. The type is compile-time information and the address it points to is runtime. The type affects the code the compiler will generate to derference and perform math on it.

Kurt Stutsman
  • 3,994
  • 17
  • 23
  • "However on systems like X86, the pointer wouldn't change value just because you cast it to a different type" --> Certainly this is common, especially with flat architectures, but on segmented(x86), Harvard, or future architectures this may not be true. I have not found "wouldn't change value" in the C standard. C specifies pointers as a separate group from integers - can't compare values unless you can one into the other. When casting a pointer with (intptr_t) to an integer, certainly the bit pattern can change. [Example answer](http://stackoverflow.com/a/3568743/2410359) may help. – chux - Reinstate Monica Feb 12 '16 at 15:47