【问题标题】:How can I use arithmetic right shifting with an unsigned int?如何使用无符号整数的算术右移?
【发布时间】:2013-02-06 04:00:12
【问题描述】:

这是一道作业题。

我需要将一个无符号的 8 位数字转换为一个有符号的 32 位数字。

例如我有这个无符号的 8 位数字:1111 1010

所以在 32 位签名中应该是 1111 1111 1111 1111 1111 1111 1111 1010

我该怎么做?我知道>> 只有在它是有符号整数时才用 1 填充,所以我可以在右移之前将其转换为有符号整数。

唯一的问题是我对我的问题有限制,这表明我需要创建一个“仅使用左移和右移以及一个减法”的函数。

【问题讨论】:

  • 将其转换为已签名。 (在有人为此叫我之前:是的,我知道这是 IB,但请给我看一个它不起作用的单一环境。)
  • 我可以,但正如我在上一段中所说,我不允许这样做
  • 您可能会在Sign extending an int in C 的答案中找到您需要的内容,它处理整数中任意位置的任意长度字段,但您在末尾有一个很好的 8 位字段整数。
  • @adamk33n3r 那么你可能应该澄清你不允许投。因为我没有捡到。
  • @Mysticial 对不起,如果你没看到我说,但我说它只能使用左右移位和一个减法

标签: c bit-manipulation


【解决方案1】:
unsigned givenByte = 0xFA;              /*This can be any given byte that we want to pad.*/
unsigned foo = (givenByte >> 7) << 8;   /*This leaves us with only the most significant bit of the original byte shifted left by one place.*/
unsigned result = givenByte - foo;

这应该返回类似于有符号算术移位的结果,除了这些操作是在无符号整数上执行的并且只使用移位和一个减法。

givenByte = 1111 1010
foo       = 0000 0000 0000 0000 0000 0001 0000 0000
result    = 1111 1111 1111 1111 1111 1111 1111 1010

这个问题每隔一段时间就会出现在 CMU 教科书和其他采用类似风格的课程中,这就是我遇到这个问题的方式。花了一些时间,但这种方法很简洁,可以应用于我们需要算术右移而无需显式转换的其他情况(我认为问题是这样提出的)。

【讨论】:

    【解决方案2】:

    通过有符号的 8 位进行转换应该可以解决问题吗?

    uint8_t start = 0xFF;
    int32_t end = (int8_t)start;
    

    或者你不允许在你的家庭作业中这样做?

    在这种情况下,向上然后向下移动将起作用,因为右移会进行符号扩展。

    uint8_t start = 0xFF;
    int32_t end = (start << 24) >> 24;
    

    【讨论】:

    • 谢谢你的回答,但我提到我不能使用投射
    • @adamk33n3r 你明白为什么转移有效吗?有符号右移的行为就好像最高位“卡”在其当前值上,因此如果将其设置为字节的高位,然后将其右移,它将“扩展”整个 int 的高位。跨度>
    • 这实际上是我想到的,但是右移一个无符号整数只是用 0 填充它,因此在 32 位中不会被解释为负数
    • @Brendan 但start 未签名,因此它不会扩展 1
    • @adamk33n3r 这确实在 gcc 上按预期工作,我没有在其他地方尝试过。正如 Brendan 所说,这是实现定义的。
    【解决方案3】:

    您需要一个合适的 32 位掩码。然后将掩码的最右边 8 位设置为 8 位无符号整数。这会给你结果。

    首先你应该自己尝试一些代码,然后尝试寻求帮助。

    【讨论】:

    • 我实际上已经尝试了一些代码,实际上大约一个小时:/“正确的”32 位掩码是什么意思?我的问题是让它同时适用于正值和负值......
    • @adamk33n3r 就目前而言,这个答案实际上几乎没有意义。所以你感到困惑是对的。因为我也是……
    • 因为您的原始 int 是 8 位无符号整数。因此,结果 32 位 int 最左边的 24 位将始终保持不变。那就是我叫面具。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 2010-12-16
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多