三个问题:NULL - NULL 定义了吗?是否已定义 (uintptr_t)NULL - (uintptr_t)NULL?

P__*_*J__ 3 c pointer-arithmetic null-pointer language-lawyer

  1. NULL - NULL定义为。?

  2. (char *)NULL - (char *)NULL定义为。?

  3. (uintptr_t)NULL - (uintptr_t)NULL定义为?

我知道它适用于我使用的所有实现。但从标准的角度来看,它是什么样子的呢?我找不到明确的答案。

编辑:从骗子看来,我认为问题的一个答案是:是的。

那么第二个问题和第三个问题呢?

chq*_*lie 7

C 标准文档NULL将其定义为宏,该宏扩展为实现定义的空指针常量

根据实际定义,表达式NULL - NULL可能有定义值,也可能没有。例如:

  • ifNULL定义为#define NULL 0, then实际上是一个值为 的NULL - NULL类型的常量表达式。int0
  • ifNULL定义为#define NULL ((void *)0),则该表达式NULL违反约束,因为算术未在 void 指针上定义。

第二个问题:(char*)NULL - (char*)NULL或者是(uintptr_t)NULL - (uintptr_t)NULL定义的?。这些表达式不再违反约束:

  • 由于从到算术类型的转换void *是实现定义的,因此不能说 的值(uintptr_t)NULL - (uintptr_t)NULL。它适用0于大多数当前系统,但 C 标准没有定义它。

  • 转换为(char *)稍微不同的事情:只有当两个指针指向同一个数组或数组最后一个元素之后的位置时,才定义两个指针的差异,在本次讨论中,一个对象被视为一个元素的数组。中的情况并非如此(char *)NULL,它是一个空指针,因此不指向任何数组或对象。

  • @P__JsupportswomeninPoland,这样改变问题的性质对于事先回答的 chqrlie 来说有点不公平。 (2认同)
  • …位于高 16 位中。因此,“void *a = &x, *b = &x;”可能会导致“a”和“b”中的不同位,即使它们指向相同的事物并且比较相等。到“uintptr_t”的转换可能被定义为包括所有 64 位,即使 16 位与地址无关。所以 `(uintptr_t) a` 可能不等于 `(uintptr_t) b`。由此可见,C 标准允许(即使不太可能)“(uintptr_t) (void *) 0 == (uintptr_t) (void *) 0”可能为 false。 (2认同)