【问题标题】:Bitshifting in C++ producing the wrong answerC++ 中的位移产生错误的答案
【发布时间】:2014-06-07 18:57:09
【问题描述】:

我尝试运行以下代码代码:

char c = (2 << 7) >> 7

应该返回 0,因为 2 的二进制表示形式为 char

0 0 0 0 0 0 1 0

左移 7 次后,我们得到 ​​p>

0 0 0 0 0 0 0 0

然后,经过七次右移,我们得到

0 0 0 0 0 0 0 0

但是,我得到的结果是 2,而不是 0。

编译器说2 &lt;&lt; 7 是256,但它是char,所以它不应该是256。

我知道2 &lt;&lt; 7 将被计算为ints 并且答案将被放入c 所以256 &gt;&gt; 7 是2。

我尝试将 2 转换为 char(例如:(char)2&gt;&gt;7),但它也不起作用。

我正在尝试从char 中提取每个位,所以我编写了以下代码:

char c = 0x02;
for(int i=0;i<7;i++)
{
    char current = (c<<i)>>7;
}

我怎样才能得到每一位?我的方式有什么问题?

【问题讨论】:

  • 2&lt;&lt;7 不是 char
  • 如果您发现问题所在,请不要将您的问题文本替换为“已修复,谢谢”。相反,添加一个解释错误的答案。
  • 我忘了,但这肯定是个骗局。
  • @hacks 很好this is similar 但不完全是一个骗局。我相信你会发现很多类似的。我想这取决于您对 dup 一词的严格程度。
  • 即使你像(char)2&gt;&gt;7这样的第一个操作数,由于默认的提升规则,它也不起作用。所有比 int 窄的类型都将自动提升为 int,并且除了在非标准编译器上之外,无法对 char 或 short 等进行数学运算

标签: c++ shift


【解决方案1】:

在 C++ 中,一个操作数为 int 的算术移位运算的结果始终是 int。因此,当你写

current = (c << i) >> 7;

C++ 会将(c &lt;&lt; i)(c &lt;&lt; i) &gt;&gt; 7 解释为ints,只有在赋值完成后才转换回char。由于临时值为ints,因此不会发生溢出,结果应该是转换为char 的整数结果。

希望这会有所帮助!

【讨论】:

  • 如何在 c++ 中不警告从 int 到 char 的转换(降级)?为什么它不需要显式转换? C++ 是类型严格的吧?
  • @texasbruce C++ 允许在其原始整数类型之间进行隐式转换,而无需显式强制转换。如果您在编译器上启动警告设置,您可能会收到有关它的警告,尽管它不是必需的。虽然 C++ 确实有静态类型,但因为它明确允许这些转换,所以没有类型错误。
  • "一个操作数" --> "左操作数"。右操作数的类型没有区别
【解决方案2】:

要得到每一位,你可以这样写:

(c >> i) & 0x01

优点:它适用于任何整数类型。

【讨论】:

  • 是的,这就是方法。在某些平台上,这只是一个位测试指令。转换类型的最大值可能会调用未定义的行为
【解决方案3】:

根据 5.8 [expr.shift] 第 1 段:

... 操作数应为整数或非范围枚举类型,并执行整数提升。结果的类型是提升的左操作数的类型。 ...

这对于类型为char 的左参数以及整数提升规则(4.5 [conv.prom])表示结果是int。当然,int 可以保存2 &lt;&lt; 7 的结果。您也可以轻松验证此行为:

#include <iostream>

void print(char c) { std::cout << "char=" << int(c) << "\n"; }
void print(int i) { std::cout << "int=" << i << "\n"; }

int main()
{
    print(2 << 7);
}

获取值位的最简单方法是使用std::bitset&lt;N&gt;N 是相应无符号类型的数字,例如:

char c('a');
std::bitset<std::numeric_limits<unsigned char>::digits> bits(c);

如果您想自己获取位,您可以使用整数类型的 unsigned 对应项来屏蔽位,例如:

template <typename T>
void get_bits(T val)
{
    typedef typename std::make_unsigned<T>::type U;
    U value(val);
    for (std::size_t s(std::numeric_limits<U>::digits); s-- != 0; ) {
        std::cout << bool(value & (1u << s));
    }
    std::cout << '\n';
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    相关资源
    最近更新 更多