C++标准中整数类型的值表示属于实现定义还是未指定行为?
我们基于N4868标准文本对该问题分析如下:
引用N4868 6.8.2第5段内容:
每个宽度为N的无符号整数类型的取值x都具有唯一表示……
值得注意的是,这段文本并未明确提及值表示(value representation)或对象表示(object representation),因此无法确认此处所指的是二者中的哪一种。
后续在N4868的*实现定义(implementation-defined)*行为索引中,明确标注了指针和浮点类型的值表示属于实现定义行为,但十分反常地没有提及整数类型。
基于此,目前存在四种可能的解读:
- 整数类型的值表示是被唯一明确规定的
- 整数类型的值表示属于*未指定(unspecified)*行为
- 整数类型的值表示属于实现定义行为,只是被误遗漏在上述索引之外
- 整数类型的值表示属于*未定义(undefined)*行为
第1种解读显然不成立,因为目前同时存在*大端(big-endian)和小端(little-endian)*架构的实现。
第3种解读的可能性极低,因为整数类型未出现在索引中是十分明显的疏漏,且浮点类型、指针类型的文本都明确标注了其值表示为实现定义,而整数类型的相关文本则刻意回避了对值表示的规定。
第2种是可能性最高的解读,但反常之处在于标准通常会明确标注未指定行为,此处却没有相关说明。这也引申出一个问题:即便标准没有明确标注,行为也可能属于未指定,这导致很难区分纯粹的未指定行为,和标准完全未作定义(而非明确标注为未定义行为(undefined behavior))而产生的未定义行为。
第4种解读显然不合理,因为标准指出所有类型(至少是*可平凡复制(trivially-copyable)*类型)都有确定的对象表示(即便未作额外规定),其值表示也同理。具体可参考6.7第4段的规定:
对于可平凡复制类型,其值表示是对象表示中用于确定取值的一组比特位,该取值是实现定义的取值集合中的一个离散元素。
这一规定似乎暗示可平凡复制类型(包括整数类型)的值表示属于未指定行为。
第2种情形很可能是标准未明确将该表示标注为“未指定”的疏漏,因为第3章“未定义行为”的定义下有注释说明:“若本文档省略了对行为的任何明确定义,则可能出现未定义行为”。如果整数类型的值表示没有被明确标注为未指定/实现定义,那么依赖该值表示的代码的行为就不是简单的未指定/实现定义,而是因标准遗漏规定而属于未定义行为。
不过也有观点认为上述“明确定义行为”的条款并不适用于该场景,因为相关行为是完全明确定义的:对象表示是unsigned char类型的对象序列,只是序列的取值由实现决定。
内容的提问来源于stack exchange,提问作者D. Detweiler

