C 将32位整数值转换为无符号16位整数值

C 将32位整数值转换为无符号16位整数值,c,types,type-conversion,integer,unsigned-integer,C,Types,Type Conversion,Integer,Unsigned Integer,C标准说明了什么: uint32_t a = 0x11223344; uint16_t b = a; 打印时,我得到0x3344,这很有意义;因此,这必须是合法和正确的行为?C标准所说的归结为这样一个事实:0x11223344通过计算模216的值,即0x3344转换为uint16\u t 然而,它到达那里的过程有几个步骤: uint16\u t b=a是带有初始化的声明,在C 2018 6.7.9 11中讨论: 标量的初始值设定项应为单个表达式,可以选择用大括号括起来。对象的初始值是表达式的初

C标准说明了什么:

uint32_t a = 0x11223344;
uint16_t b = a;

打印时,我得到0x3344,这很有意义;因此,这必须是合法和正确的行为?

C标准所说的归结为这样一个事实:
0x11223344
通过计算模216的值,即
0x3344
转换为
uint16\u t

然而,它到达那里的过程有几个步骤:

uint16\u t b=a是带有初始化的声明,在C 2018 6.7.9 11中讨论:

标量的初始值设定项应为单个表达式,可以选择用大括号括起来。对象的初始值是表达式的初始值(转换后);应用与简单赋值相同的类型约束和转换,将标量的类型作为其声明类型的非限定版本

因此,简单赋值的规则适用。这些在6.5.16.1.2中讨论:

在简单赋值(=)中,右操作数的值转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值

根据6.5.16.3,“赋值表达式的类型”是左操作数的类型:

赋值表达式的类型是左值转换后左操作数的类型

(在这种情况下,左值转换没有什么显著的意义;对象
uint16\u t b
将简单地变成
uint16\u t
值,因此类型是
uint16\u t

当然,根据7.20.1.1的规定,
uint16\u t
的类型是一个无符号16位整数:

typedef nameuintN\u t指定宽度为N且无填充位的无符号整数类型

请注意,作为无符号16位整数,其最大值为65535,比该值多出一个值为65536(216)。这与最后一步有关,即从右操作数到
uint16\u t
的转换,将在6.3.1.3 1和2中讨论:

当整数类型的值转换为除\u Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变

否则,如果新类型是无符号的,则会通过重复地将新类型中可以表示的最大值加上或减去一个值来转换该值,直到该值在新类型的范围内


当我们从
0x11223344
0x1122
中减去65536(
0x10000
)次时,结果是
0x3344
,可以用
uint16表示,这是转换的结果。

这是合法和正确的行为。您的意思是将
32
分配给
16
!这是一件正确的事情,但是得到一个合理的结果并不能证明这一点。从一个程序在某种情况下产生所需的输出这一事实推断它是合法和正确的是不正确的。接受程序正确性的适当方法是理解适用的规则(如编译器和语言规范),并检查程序是否符合这些规则。当然,在实际执行中进行实验是非常宝贵的,但是理解规则也是非常宝贵的。埃里克,谢谢你全面的回答。