所有位0都可以是整数的陷阱表示吗?

时间:2017-11-01 13:26:19

标签: c language-lawyer undefined-behavior calloc

通常假设将对象初始化为所有位0是将其所有成员设置为0的简单方法。对于非整数类型,标准不保证:

  • 所有位零可能不是指针的有效表示,即使是空指针,尽管所有常见的现代系统都使用它。
  • 所有位零可能不是浮点数的合法表示,尽管它在IEEE兼容系统上。

整数怎么样?是否完全定义了以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    int *p = calloc(sizeof(*p), 1);
    if (p) {
        printf("%d\n", *p);
        memset(p, 0, sizeof(*p));
        printf("%d\n", *p);
        free(p);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:10)

来自C Standard, 6.2.6.2, Integer Types

  

对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示。

答案 1 :(得分:2)

陷阱表示的定义是,C11 6.2.6.1/5:

  

某些对象表示不需要表示对象类型的值。如果存储   对象的值具有这样的表示,并由左值表达式读取   没有字符类型,行为是未定义的。如果产生这样的表示   通过副作用,通过左值表达式修改对象的全部或任何部分   没有字符类型,行为是未定义的.50)这样的表示被调用   陷阱表示。

这意味着陷阱表示必须是不是有效值的东西。

在二进制补码的情况下,int的所有二进制组合都是有效值,因此陷阱表示是不可能的。

如果是虚构的一个补码系统,如果不支持负零,则可以使值0xFFFFFFFF(假设32位为int)成为陷阱表示。同样,在一个虚构的签名量级系统上,值0x80000000可以用作陷阱表示。

在更加虚弱的虚构系统中,整数可能有填充位,然后这样的填充位可用于保存陷阱表示。

在任何这些情况下,二进制表示0始终是值。许多C标准依赖于此,例如具有静态存储持续时间的对象的初始化,calloc()函数,结构中的填充字节的值等等。在所有这些中,结果不应是陷阱表示。

请注意,如果您不是一个狂野虚构系统的程序员,那么这一切都无关紧要。可能存在一些奇怪的,实验性的计算机,这是一件事。你甚至可能找到一个可以告诉你关于他们的活着的人。

如果您正在设计与这些奇特的,最可能虚构的系统的兼容性,您应该详细记录为什么您的产品需要这种兼容性。因为你的老板可能想知道为什么你花了很多时间设计兼容现实世界中实际不存在的计算机。