(size_t)((char *)0)是否曾评估为0?

时间:2010-04-05 22:20:44

标签: c compiler-construction pointers casting standards-compliance

根据"Why subtract null pointer in offsetof()?"中的回答(以及我对K& R的解读),C标准不要求(size_t)((char *)0) == 0。尽管如此,我还没有看到过将指向整数类型的空指针计算为其他任何内容的情况。

如果有(size_t)((char *)0) != 0的编译器或场景,它是什么?

4 个答案:

答案 0 :(得分:4)

嗯,如您所知,给定类型的空指针的物理表示不一定是全零位模式。当您强制将指针(任何指针)值转换为整数类型时,结果是实现定义的,但通常(并且这是意图)指针的数值 - 数字地址 - 如果可能的话保持不变。这意味着如果在给定平台上,char *类型的空指针由0xBAADF00D模式表示(例如),则上述表达式将计算为0xBAADF00D,而不是零。当然,为此你需要一个非零空指针的平台。我个人从未使用过这样的平台,虽然我听说过很多像这样的真实平台(比如,在嵌入式平台领域,这并不是什么不寻常的事情)。

此外,作为附加说明,不同类型的空指针值可以具有不同的物理表示,这意味着理论上您可以从(size_t) ((int *) 0)(size_t) ((char *) 0)(size_t) ((double *) 0)获得不同的值。但是从抽象的C语言的角度来看,这将是一个相当奇特的情况,尽管完全可能。

P.S。有关具有非零空指针的实际平台的一些示例,请阅读here(C FAQ)。

答案 1 :(得分:1)

C标准唯一需要空指针运行时表示的是(6.3.2.3/3“指针”):

  

...结果指针(称为空指针)保证与指向任何对象或函数的指针不相等。将空指针转换为另一种指针类型会产生该类型的空指针。

     

任何两个空指针都应该相等。

但你的问题很有意思。就个人而言,我不知道没有使用运行时值0表示空指针的平台。但是,标准并不要求它,所以如果你能避免代码中的假设,为什么不呢?

我也对任何知道系统的人感兴趣,该系统对空指针使用非零运行时值。

答案 2 :(得分:1)

C99标准规定,当您将整数值0转换为指针时,它将变为NULL指针。所以((char*)0)是一个NULL指针。 NULL指针不需要具有0的实际二进制表示。它可以是,例如0x12345678

C标准进一步指出,当您将NULL指针转换为整数常量时,结果是“实现定义的”。实际上,正如AndreyT所说,编译器所做的只是将指针的数值转换为相应的整数值。所以在上面的例子中,整数值最终可能是0x12345678,虽然从技术上讲它可能是任何东西(即允许编译器说“将NULL指针转换回整数值会产生值{ {1}}“)。请注意,这意味着即使在NULL指针具有值0xDEADBEEF的平台上,也允许编译器在转换时将其转换为任意整数值。然而,实际上,没有编译器会这样做,因为它会相当疯狂。

所以,是的,C标准允许很多东西。实际上,您可能正在处理的任何平台都将NULL指针表示为0,将NULL指针转换为整数值将导致0。查看here (section 1.14)以获取(隐藏)架构的一些例外列表,这些架构不使用0作为NULL指针。

答案 3 :(得分:0)

这不适用于char*甚至C,但是索引到数组中的智能指针类可能会选择将NULL表示为-1,因为0是一个有效的数组索引。

考虑到memset( my_new_struct, 0, sizeof my_new_struct );的成语,即使以调试为中心的系统也不太可能打破这种身份。