Mar*_*ark 4 c types integer type-conversion unsigned-integer
C 标准怎么说:
uint32_t a = 0x11223344;
uint16_t b = a;
Run Code Online (Sandbox Code Playgroud)
打印时,我得到 0x3344,这是有道理的;所以这必须是合法和正确的行为?
C 标准所说的归结0x11223344为uint16_t通过计算值模 2 16转换为的事实,即0x3344.
然而,它到达那里的过程有几个步骤:
uint16_t b = a; 是带有初始化的声明,在 C 2018 6.7.9 11 中讨论过:
标量的初始值设定项应为单个表达式,可选地括在大括号中。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换适用,将标量的类型作为其声明类型的非限定版本。
所以简单分配的规则适用。这些在 6.5.16.1 2 中讨论:
在简单赋值( = ) 中,右操作数的值被转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值。
根据 6.5.16 3,“赋值表达式的类型”是左操作数的类型:
赋值表达式的类型是左操作数在左值转换后的类型。
(在这种情况下,左值转换没有什么特别之处;对象uint16_t b只是变成一个uint16_t值,所以类型是uint16_t。)
的类型uint16_t当然是一个无符号的 16 位整数,根据 7.20.1.1 1:
typedef 名称uint N _t指定宽度为N且无填充位的无符号整数类型。
需要注意的是,作为一个无符号的16位整数,其最大值为65535,再增加一个为65536(2 16)。这与最后一步有关,即从右操作数到 的转换uint16_t,这在 6.3.1.3 1 和 2 中讨论:
当一个整数类型的值被转换为_Bool以外的另一个整数类型时,如果该值可以用新类型表示,则不变。
否则,如果新类型是无符号的,则通过重复加或减一个新类型可以表示的最大值来转换该值,直到该值在新类型的范围内。
乘以65536( 0x10000) 0x11223344 0x1122,得到的结果是0x3344,可以用a表示uint16_t,这就是转换的结果。