[英]Confusion with a type that has members char *ptr; size_t used; size_t size?
[英]Does (size_t)((char *)0) ever not evaluate to 0?
根据“为什么在offsetof()中减去空指针?”中的响应。 (以及我对K&R的阅读),C标准不需要(size_t)((char *)0) == 0
。 尽管如此,我从未见过将空指针强制转换为整数类型会影响其他任何情况的情况。
如果存在(size_t)((char *)0) != 0
的编译器或方案,那是什么?
众所周知,给定类型的空指针的物理表示不一定是全零位模式。 当您将指针(任何指针)的值强制转换为整数类型时,结果是实现定义的,但是通常(这是目的)指针的数值(数字地址)尽可能保持不变。 这意味着,如果在给定平台上用0xBAADF00D
模式(例如)表示char *
类型的空指针,则上述表达式的计算结果为0xBAADF00D
,而不是零。 当然,为此,您将需要一个具有非零空指针的平台。 我个人从来没有使用过这样的平台,尽管我听说过那里有很多类似的真实平台(例如,在嵌入式平台领域这并不稀奇)。
此外,需要特别注意的是,不同类型的空指针值可以具有不同的物理表示形式,这意味着从理论上讲,您可以从(size_t) ((int *) 0)
, (size_t) ((char *) 0)
获得不同的值。和(size_t) ((double *) 0)
。 但这将是一个相当奇特的情况,尽管从抽象C语言的角度来看这是完全可能的。
PS 在此处阅读(C FAQ),了解带有非零空指针的实际平台的一些示例。
C标准要求空指针的运行时表示的唯一内容是(6.3.2.3/3“ Pointers”):
...得到的指针称为空指针,保证将不相等的指针与指向任何对象或函数的指针进行比较。 将空指针转换为另一种指针类型会产生该类型的空指针。
任何两个空指针应比较相等。
不过,您的问题很有趣。 就个人而言,我不知道没有使用运行时值0表示空指针的平台。 但是,该标准不需要它,因此,如果可以避免代码中的假设,为什么不这样做呢?
我也会对知道使用空指针的非零运行时值的系统的任何人感兴趣。
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指针。
这不适用于char*
甚至C,但是对数组进行索引的智能指针类可能选择将NULL
表示为-1
因为0
是有效的数组索引。
考虑memset( my_new_struct, 0, sizeof my_new_struct );
的成语memset( my_new_struct, 0, sizeof my_new_struct );
,即使以调试为中心的系统也不太可能破坏该身份。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.