1

Related to: Three questions: Is NULL - NULL defined? Is (uintptr_t)NULL - (uintptr_t)NULL defined?

Lets consider:

  1. Case 1: (uintptr_t)NULL - (uintptr_t)NULL will the result always be zero?

  2. Case 2 (ispired by the Eric comment):

uintptr_t x = (uintptr_t)NULL;

will x - x be always zero?

  1. case 3:
uintptr_t x = (uintptr_t)NULL, y = (uintptr_t)NULL;

Will x-y be always zero?

  1. Case 4:
void *a; 

/* .... */

uintptr_t x = (uintptr_t)a, y = (uintptr_t)a;

Will x-y be always zero?

If not - why?

0___________
  • 47,100
  • 4
  • 27
  • 62
  • 1
    Do you ask theoretically or practically? Because I can write a compiler, and document that on in my custom compiler "the expression NULL - NULL is equal to 0, except when on line 12, then it's equal to 62" and it still will be "implementation defined" (just insane). If such compiler can still reach a conforming behavior of the program (ie. it will track which pointers where converted on which line within the pointer value), then it could be fine. – KamilCuk Nov 08 '20 at 17:39
  • @KamilCuk do it ! :D – Cid Nov 08 '20 at 17:40
  • @KamilCuk do you know what "language-lawyer" tag mean? – 0___________ Nov 08 '20 at 20:09

2 Answers2

2

Can two implementation defined identical expressions give different results?

Yes. It's "implementation-defined" - all rules are up to implementation. An imaginary implementation may look like this:

int main() {
      void *a = 0;
#pragma MYCOMPILER SHIFT_UINTPTR 0
      printf("%d\n", (int)(uintptr_t)a); // prints 0
#pragma MYCOMPILER SHIFT_UINTPTR 5
      printf("%d\n", (int)(uintptr_t)a); // prints 5
}

Still such an implementation would be insane on most platforms.

I could imagine a example: architecture that has to deal with memory in "banks". A compiler for that architecture uses a #pragma switch to select the "bank" that is used for dereferencing pointers.

  1. (uintptr_t)NULL - (uintptr_t)NULL will the result always be zero?

Not necessarily.

  1. will x - x be always zero?

Yes. uintptr_t is an unsigned integer type, it has to obey the laws of mathematics.

  1. Will x-y be always zero?

Not necessarily.

  1. Will x-y be always zero?

Not necessarily.

If not - why?

The result of conversion from void* to uintptr_t is implementation defined - the implementation may convert the pointer value to different uintptr_t value each time, which would result in a non-zero difference between the values.

I could see a example: on some imaginary architecture pointers have 48-bits, while uintptr_t has 64-bits. A compiler for such architecture just "doesn't care" what is in those 16 extra bits and when converting uintptr_t to a pointer it uses only the 48-bits. When converting pointer to an uintrpt_t compiler uses whatever garbage value was leftover in registers for the extra 16-bits, because it's fast to do that in that specific architecture and because they will never be used when converting back..

KamilCuk
  • 96,430
  • 6
  • 33
  • 74
  • (int)(uintptr_t) is not something I am asking about.# – 0___________ Nov 08 '20 at 19:55
  • `#pragma MYCOMPILER SHIFT_UINTPTR 5 printf("%d\n", (int)(uintptr_t)a); // prints 5` and `#pragma MYCOMPILER SHIFT_UINTPTR 0 printf("%d\n", (int)(uintptr_t)a); // prints 0` are two distinct expressions. They are not the same. – 0___________ Nov 08 '20 at 20:03
0

You won't find a system in use anywhere where NULL isn't defined as some form of 0, be it the literal value or a void * with value 0, so all of your checks will either work as you'd expect or be syntax errors (can't subtract void * values).

Is it possible to be defined as anything else though? Theoretically. Though it's still a constant, so subtracting them (language and type allowing) will still equal 0.

Blindy
  • 60,429
  • 9
  • 84
  • 123
  • I am not asking about the implementations. The question is about the **C standard**. Read the tags – 0___________ Nov 08 '20 at 19:58
  • `You won't find a system in use anywhere where NULL isn't defined as some form of 0` ny_killer_compiller : `#define NULL -1`. Now you have an implementation – 0___________ Nov 08 '20 at 20:12
  • @P__JsupportswomeninPoland _`#define NULL -1`. Now you have an implementation_ Which is not conforming. – Language Lawyer Nov 09 '20 at 06:51
  • _You won't find a system in use anywhere where `NULL` isn't defined as some form of `0`._ Possibly not now, but did you see the [When was the NULL macro not 0?](https://stackoverflow.com/questions/2597142/when-was-the-null-macro-not-0) thread? It does not conform current standards, which require null pointer to yield zero when cast to integral types. However, the latter applies to integral _conversion_ only, the internal representation of the null pointer needn't be zero-bytes only. – CiaPan Jun 10 '21 at 15:24