【问题标题】:Converting 32-bit integer value to unsigned 16-bit integer将 32 位整数值转换为无符号 16 位整数
【发布时间】:2019-05-30 10:36:03
【问题描述】:

C 标准是怎么说的:

uint32_t a = 0x11223344;
uint16_t b = a;

打印时,我得到 0x3344,这是有道理的;所以这一定是合法且正确的行为吗?

【问题讨论】:

  • 这是合法正确的行为。port70.net/~nsz/c/c11/n1570.html#6.3.1.3
  • 你的意思是把32分配给16
  • 这是正确的做法,但获得合理的结果并不能证明这一点
  • 从程序在一种情况下产生所需输出这一事实推断它是合法且正确的是不正确的。接受程序正确性的正确方法是了解适用的规则(例如编译器和语言规范)并检查程序是否符合这些规则。当然,尝试实际执行是非常宝贵的,但理解规则也是如此。

标签: c types type-conversion integer unsigned-integer


【解决方案1】:

C 标准所说的归结为 0x11223344 通过计算模 216 的值转换为 uint16_t,即 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 名称 uintN_t 指定宽度为 N 且无填充位的无符号整数类型。

注意,作为无符号的 16 位整数,其最大值为 65535,大于 1 为 65536 (216)。这与最后一步有关,即从右操作数转换为uint16_t,这将在 6.3.1.3 1 和 2 中讨论:

当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的类型表示,则保持不变。

否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上反复加减一,直到该值在新类型的范围内。

当我们用0x112233440x1122次减去65536(0x10000),结果是0x3344,可以用uint16_t表示,所以就是转换的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多