6.2.6 类型的表示
6.2.6.1 一般规定
除本小节明确规定的情况外,所有类型的表示都未作规定。
除位字段外,对象都由一个或多个连续字节组成;这些字节的数量、顺序和编码,要么被明确规定,要么由实现定义。
存储在无符号位字段以及
unsigned char类型对象中的值,必须采用纯二进制记法表示。对于其他任何非位字段对象类型,存储的值都用
n × CHAR_BIT位表示,其中n是该类型对象的大小(以字节计)。一个具有该值的对象,可以被复制到一个unsigned char[n]类型对象中(例如使用memcpy);所得字节集合称为该值的对象表示。位字段中存储的值由m位组成,其中m是该位字段指定的宽度。其对象表示,就是承载该位字段的可寻址存储单元中属于它的那m位。两个值(NaN 除外)如果具有相同对象表示,则比较结果相等;但比较结果相等的值,未必具有相同对象表示。某些对象表示并不表示该对象类型中的某个值。如果这样的表示通过一个非字符类型左值表达式被读取,则行为未定义。如果这样的表示是通过某个不具有字符类型的左值表达式,对该对象全部或部分内容进行修改所产生的副作用形成的,则行为未定义。43)这种表示称为非值表示。
当某个值被存入结构体类型或联合体类型对象中时(包括存入其成员对象中),对象表示中对应于任何填充字节的那些字节,会取得未指定值(例如,结构体赋值和联合体赋值可能会复制填充位,也可能不会)。结构体或联合体对象的对象表示本身永远不是非值表示,即使其中与某个成员对应的字节范围,对该成员而言可能属于非值表示。
当某个值被存入联合体对象的一个成员时,对应于其他成员、但不对应于当前成员的那些对象表示字节,会取得未指定值。
如果某个运算符作用于一个具有多种对象表示的值,那么究竟使用哪一种对象表示,不得影响结果的值。44)如果使用某个“对同一值存在多种对象表示”的类型把值存入对象,则使用哪一种表示未作规定,但不得产生非值表示。
对原子类型对象的加载与存储,使用
memory_order_seq_cst语义完成。
前向引用:声明(6.7)、表达式(6.5.1)、左值、数组和函数指示符(6.3.2.1)、顺序和一致性(7.17.3)。
6.2.6.2 整数类型
对于无符号整数类型,其对象表示中的位应划分为两组:值位和填充位。若共有
N个值位,则每一位都应表示1到2^(N-1)之间某个不同的 2 的幂,因此该类型对象必须能够使用纯二进制表示法表示从0到2^N - 1的值;这称为该类型的值表示。任何填充位的值都是未指定的。值位数N称为该无符号整数类型的宽度。bool类型应有 1 个值位,以及(sizeof(bool) * CHAR_BIT) - 1个填充位。除此之外,不要求一定存在填充位;unsigned char不得含有填充位。对于有符号整数类型,其对象表示中的位应划分为三组:值位、填充位和符号位。若其对应无符号类型的宽度为
N,则有符号类型使用同样数量的N位作为其宽度,其中N - 1位是值位,剩下 1 位是符号位。每个值位所表示的值,都应与对应无符号类型对象表示中的相同位相同。若符号位为0,则它不影响最终值;若符号位为1,则它的值是-(2^(N-1))。填充位可以有,也可以没有;signed char不得含有填充位。任何填充位的值都是未指定的。若某个有符号整数类型的对象表示是有效的,并且它的符号位为
0,那么该对象表示也是对应无符号类型的有效对象表示,并且表示相同的值。对于任何整数类型,全体位都为0的对象表示,都必须表示该类型中的值0。整数类型的精度,就是它的值位数。
注 1:某些填充位组合可能会产生非值表示,例如当某一填充位承担奇偶校验位作用时。尽管如此,对有效值进行的任何算术运算,都不会生成非值表示;唯一的例外是把它作为某种异常情形(如整数溢出)的一部分时。所有其他填充位组合,都是由值位所确定那个值的备用对象表示。
注 2:本文档定义的这种有符号表示,称为二进制补码(two’s complement)。本文档的早期版本(特别是 ISO/IEC 9899:2018 及之前版本)还允许其他有符号表示方式。
注 3:对于无符号整数类型,宽度和精度相同;对于有符号整数类型,宽度比精度大 1。
脚注说明
43)如果通过字符类型左值表达式访问对象表示,则不受这里这条限制约束。
44)这里说的是值不受影响,而不是位级表示必须保持不变。