(size_t)((char *)0) 的计算结果是否不是 0?

问题描述 投票:0回答:4

根据“为什么要在 offsetof() 中减去空指针?”(以及我对 K&R 的阅读)中的回答,C 标准并不要求这样做

(size_t)((char *)0) == 0
。不过,我从未见过将空指针转换为整数类型会计算出其他值的情况。

如果有一个编译器或场景

(size_t)((char *)0) != 0
,那是什么?

c pointers casting standards-compliance
4个回答
4
投票

正如您所知,给定类型的空指针的物理表示不一定是全零位模式。当您强制将指针(任何指针)值转换为整数类型时,结果是实现定义的,但通常(这就是意图)指针的数值(数字地址)如果可能的话保持不变。这意味着,如果在给定平台上,类型为

char *
的空指针由
0xBAADF00D
模式表示(例如),则上述表达式的计算结果将为
0xBAADF00D
,而不是零。当然,为此您需要一个具有非零空指针的平台。我个人从未使用过此类平台,尽管我听说过许多类似的真实平台(例如,在嵌入式平台领域,这并不罕见)。

此外,作为补充说明,不同类型的空指针值可以有不同的物理表示,这意味着理论上您可以从

(size_t) ((int *) 0)
(size_t) ((char *) 0)
(size_t) ((double *) 0)
获得不同的值。但这将是一种相当奇特的情况,尽管从抽象 C 语言的角度来看这是完全可能的。

附注请阅读此处(C 常见问题解答),了解具有非零空指针的实际平台的一些示例。


1
投票

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

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

任意两个空指针比较应该相等。

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

我也对任何了解使用非零运行时值作为空指针的系统的人感兴趣。


1
投票

C99 标准规定,当您将整数值

0
转换为指针时,它会变成 NULL 指针。所以
((char*)0)
是一个 NULL 指针。 NULL 指针不需要有
0
的实际二进制表示。例如,它可以是
0x12345678

C 标准进一步指出,当将 NULL 指针转换为整型常量时,结果是“实现定义的”。实际上,正如 AndreyT 所说,编译器所做的只是将指针的数值转换为相应的整数值。因此,在上面的示例中,整数值最终可能是

0x12345678
,尽管从技术上讲它可以是任何东西(即编译器可以说“将 NULL 指针转换回整数值会导致值
0xDEADBEEF
”) ”)。请注意,这意味着即使在 NULL 指针具有值
0
的平台上,编译器也可以在转换时将其转换为任意整数值。但实际上,没有编译器这样做,因为这相当疯狂。

所以,是的,C 标准允许很多事情。实际上,您可能使用的任何平台都将 NULL 指针表示为

0
,并将 NULL 指针转换为整数值将导致
0
。请查看此处(第 1.14 节),了解不使用
0
作为 NULL 指针的(模糊)架构的一些例外情况。


0
投票

这不适用于

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

考虑到

memset( my_new_struct, 0, sizeof my_new_struct );
的习惯用法,即使是以调试为中心的系统也不太可能打破这一特性。

© www.soinside.com 2019 - 2024. All rights reserved.