C 标准说了什么:
uint32_t a = 0x11223344;
uint16_t b = a;
打印时,我得到 0x3344,这是有道理的;所以这一定是合法和正确的行为?
最佳答案
C 标准所说的归结为 0x11223344
通过计算模 216 的值转换为 uint16_t
,即0x3344
。
但是,它到达那里的过程有几个步骤:
uint16_t b = a;
是带有初始化的声明,在C 2018 6.7.9 11中讨论:
The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type.
因此适用简单赋值规则。这些在 6.5.16.1 2 中讨论:
In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.
“赋值表达式的类型”是左操作数的类型,根据 6.5.16 3:
The type of an assignment expression is the type the left operand would have after lvalue conversion.
(在这种情况下,左值转换没有什么特别之处;对象 uint16_t b
只会变成一个 uint16_t
值,所以类型是 uint16_t
.)
根据 7.20.1.1 1,uint16_t
的类型当然是一个无符号的 16 位整数:
The typedef name uintN_t designates an unsigned integer type with width N and no padding bits.
请注意,作为一个无符号的 16 位整数,其最大值为 65535,再多一则为 65536(216)。这与最后一步有关,即从右操作数到 uint16_t
的转换,这在 6.3.1.3 1 和 2 中讨论:
When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
当我们将0x11223344
0x1122
次减去65536(0x10000
),结果为0x3344
,可以由 uint16_t
表示,因此这是转换的结果。
关于将 32 位整数值转换为无符号 16 位整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54029050/