【问题标题】:Bit shifting in c with negative values [duplicate]c 中带有负值的位移[重复]
【发布时间】:2015-06-21 21:13:13
【问题描述】:
int16_t a = -1;
a >>= 2;

a的值是多少, 答案是 -1 还是 0,你能解释一下原因吗?

是否发生整数除法,然后使用 floor 函数,或者它只是将 2s 补码中的所有 1 向右移动,从而导致仍然为 -1 还是截断除法导致 0。

【问题讨论】:

  • 为什么不运行代码看看?
  • 因为我在 9 点参加笔试 tmrw 我的电脑上没有开发环境,哈哈
  • 有符号整数右移的结果是实现定义的。它可能是算术或逻辑移位,具体取决于是否传播符号位。
  • @joelgoldstick:幸好他没有“运行代码并查看”。由于这是实现定义的行为,他会知道他的编译器是如何实现它的,但绝对不会知道其他编译器是如何实现它的。 “运行看看”可能是一个非常危险的工具!

标签: c bit-manipulation


【解决方案1】:

对于 C 语言草案 6.5.7 移位运算符 5:

E1 >> E2 的结果是 E1 右移 E2 位位置。如果 E1 有 一个无符号类型,或者如果 E1 有一个有符号类型和一个非负值, 结果的值是 E1 / 商的整数部分 2E2。如果 E1 具有带符号类型和负值,则 结果值是实现定义的

这意味着它不是未定义的行为是正确的,但每个编译器可能会决定用 1 或 0 填充位。

然后结果可以是 -1(用 1 位填充)或 16383 = 0x3FFF(用 0 位)

【讨论】:

  • ... 或任何其他值。实现定义意味着实现可以定义结果值,无论它选择如何,就像未定义或未指定一样。 UB 和实现定义的行为之间的区别在于实现的手册必须记录实现定义的行为。
【解决方案2】:

当我们进行右移时,有符号数据类型的符号位保持不变,因此如果 a 等于 -1数据的所有位都是 1。如果我们不管多少位都右移,数据的值保持不变。所以a 的值仍然是-1。这是大多数编译器发生的情况。但答案取决于编译器的实现

【讨论】:

    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2014-05-26
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多