通过示例的对象和值表示之间的差异

时间:2014-10-07 17:05:36

标签: c++ memory language-lawyer

N3797::3.9/4 [basic.types]

  

类型为T的对象的对象表示是N的序列   由类型T的对象占用的unsigned char对象,其中N等于   的sizeof(T)。对象的值表示是位集   保持类型T的值。对于简单的可复制类型,值   表示是对象表示中的一组位   确定一个值,它是一个离散元素   实现定义的值集

N3797::3.9.1 [basic.fundamental]说:

  

对于窄字符类型,对象表示的所有位   参与价值代表。

考虑以下结构:

struct A
{
    char a;
    int b;
}

我认为对于A,由于实现添加了填充,因此对象表示的所有位都不参与值表示。但其他基本类型呢? 标准说: N3797::3.9.1 [basic.fundamental]

  

对于窄字符类型,对象表示的所有位   参与价值代表。   这些要求适用于其他类型。

我无法想象为什么它不能代表intlong。原因是什么?你能澄清一下吗?

3 个答案:

答案 0 :(得分:6)

一个例子可能是Unisys大型机,其中int有48个 比特,但只有40个参与值表示(而INT_MAX是2 ^ 39-1);该 其他人必须是0.我想任何带有标记的机器 架构会有类似的问题。

编辑:

更多信息:Unisys大型机是 可能是唯一真正存在的架构 异国情调:Unisys Libra(前Burroughs)有48位字,使用签名 整数的大小,并有一个标记的架构,在哪里 数据本身包含有关其类型的信息。该 Unisys Dorado是前Univac:36位的补充(但没有 用于标记的保留位)和9位字符。

然而,根据我的理解,Unisys正在逐步淘汰它们(或者 已经在去年逐步淘汰了他们,支持基于英特尔的 系统。一旦它们消失,几乎所有系统都会消失 2 +补码,32或64位,以及除IBM大型机之外的所有 将使用IEEE浮动(并且IBM正在移动或已经移入 那个方向也是如此)。所以没有任何动力 继续采用特殊措辞支持他们的标准; 最后,在lesat的几年内,C / C ++可能就可以了 遵循Java路径,并对其所有进行表示 基本数据类型。

答案 1 :(得分:3)

这可能意味着在某些平台上为编译器提供空间优化。

例如考虑一个64位平台,其中处理非64位值会产生很大的损失,那么有必要对其进行处理。 short只使用16位(值repr),但仍然使用64位存储(obj repr)。

类似的理由适用于<stdint>规定的最快最小宽度整数类型。有时较大的类型不会慢,但使用起来会更快。

答案 2 :(得分:3)

据我所知,至少有一个案例是处理陷阱表示,通常是在异国情调的架构上。 N2631: Resolving the difference between C and C++ with regards to object representation of integers中介绍了此问题。这是很长但我会引用一些部分(作者是詹姆斯坎泽,所以如果我们幸运的话,他可能会过去并进一步评论)这说(强调我的 >)。

  

最近在comp.lang.c ++中的讨论中,很明显C和C ++对整数的对象表示具有不同的要求,并且至少有一个C的实际实现不符合C ++要求。本文的目的是建议措辞以使C ++标准与C一致。

     

应该注意的是,该问题仅涉及一些相当“异国情调”的硬件。在这方面,它提出了一个更大的问题

  

如果需要C兼容性,在我看来,最简单和最可靠的方法是通过合并C标准中的确切单词代替当前的措辞。因此,我建议采用C标准中的措辞,如下

  

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

  

对于有符号整数类型[...] 其中哪一个适用于实现定义,是符号位1和所有值位为零的值(前两个),还是符号位和所有值位1(对于一个补码),是陷阱表示或正常值。在符号和幅度以及一个补码的情况下,如果该表示是正常值,则称为负零。