C ++引发溢出

时间:2017-09-28 12:18:35

标签: c++

读取位组,我为自己写了一个小函数, 它读取一个位组并返回该值。实际上,我想 附加的示例应导致以下命令中的溢出

(BitGroupMask << BitGroupPosition)

根据标准,中间结果被解释为整数。 但是,结果对于所有测试值都是正确的。显然,编译器会检查整个Expression中的最大数据类型。至少,我猜。

我的问题:行为是依赖于编译器还是在C ++标准中定义?

代码:

#include <iostream>
#include <bitset>


using namespace std;


uint64_t Variable{0b1011111111111111111111111111111111111111111111111111111111111111ULL};
uint8_t GMask{0b1111};
uint8_t GPos{60};


template <typename VarType, typename MaskType>
inline VarType readBitGroup(VarType Var, MaskType BitGroupMask, MaskType BitGroupPosition)
{
    //return (VarType)((Var & ((VarType)BitGroupMask << BitGroupPosition)) >> BitGroupPosition);
    return ((Var & (BitGroupMask << BitGroupPosition)) >> BitGroupPosition);
}


int main()
{
    cout << std::bitset<64>(Variable) << std::endl;
    cout << std::bitset<4>(readBitGroup(Variable, GMask, GPos)) << std::endl;
    return 0;
}

2 个答案:

答案 0 :(得分:2)

有问题的代码是

uint8_t GMask{0b1111};
uint8_t GPos{60};
... (GMask << GPos) ...

如果我正确阅读标准

  

操作数应为整数或无范围的枚举类型,并执行整体促销。该   结果的类型是提升的左操作数的类型。如果右操作数是,则行为未定义   否定的,或大于或等于提升的左操作数的位长度。

你的uint_8操作数被提升,然后发生转变。

  

除bool,char16_t,char32_t或wchar_t之外的整数类型的整数转换的整数转换   如果int可以表示所有的,则rank(7.15)小于int的等级可以转换为int类型的prvalue   源类型的值;否则,源prvalue可以转换为unsigned int类型的prvalue。

第二个引号指定将值提升为int - 因为它足以表示值15和60.

然后 - 回到第一个引用我们看到行为未定义

因此,您有责任将班次的左操作数转换为足以存储班次结果的类型。

答案 1 :(得分:1)

是的,你是对的,行为是未定义的。使用以下值,我得到了错误的结果:

uint64_t Variable{0b1111111110111111111111111111111111111111111111111111111111111111ULL};
uint8_t GMask{0b1111};
uint8_t GPos{52};

所以我将行扩展到

return ((Var & ((VarType)BitGroupMask << BitGroupPosition)) >> BitGroupPosition);

现在它正在运作。谢谢你的帮助!