【问题标题】:Can all bits 0 be a trap representation for integers?所有位 0 都可以是整数的陷阱表示吗?
【发布时间】:2018-04-13 20:02:18
【问题描述】:

通常假设将对象初始化为所有位 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;
}

【问题讨论】:

  • 为什么要这样做?您是否正在寻找一种将任何内存初始化为某种“安全”值的通用方法?
  • 我不明白这个问题...你知道 calloc 与 malloc+memset zero 是一回事吗?为什么要额外的 memset?

标签: c language-lawyer undefined-behavior calloc


【解决方案1】:

来自C Standard, 6.2.6.2, Integer Types

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

【讨论】:

    【解决方案2】:

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

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

    这意味着陷阱表示必须是无效值。

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

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

    在更疯狂的虚构系统上,整数可能具有填充位,然后此类填充位可用于保存陷阱表示。

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

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

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

    【讨论】:

    • 在 C89 之前,如果整数没有设置某些填充位,即使所有数据位的值都为零,系统也允许使用会捕获的表示。在这样的系统上,需要静态初始化才能将整数初始化为有效的零值,但这并不是特别奇特的要求,因为即使在 C99 下,指针和浮点值的默认初始化也可能需要除所有位之外的位模式零。
    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 2016-10-28
    • 2014-07-24
    相关资源
    最近更新 更多