这是运算符<<的正确实现吗? />&gt ;?

时间:2011-06-27 05:07:55

标签: c++ math operator-overloading bitwise-operators bit-shift

是运算符的这些正确实现<<和>>比特换档?出于某种原因,在我的操作员/中,只涉及这两个操作员,有些东西允许愚蠢的跳跃,导致分割错误。

    // the value is stored msb in a list of uint8_t
    // so 0x123456 will be stored in the list as {0x12, 0x34, 0x56}
    integer operator<<(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.push_back(0);
        shift &= 7;
        if (shift){
            out.push_front(0);
            std::list <uint8_t>::iterator i = out.begin(), j = out.end();
            i++; j--;
            for(; i != j; i++){
                uint8_t temp = *i >> (8 - shift);
                --i;
                *i += temp;
                i++;
                *i = (uint8_t) (*i << shift);
            }
            uint8_t temp = *i >> (8 - shift);
            i--;
            *i += temp;
            i++;
            *i <<= shift;
        }
        return integer(out);
    }

    integer operator>>(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.pop_back();
        shift &= 7;
        if (shift){
            std::list <uint8_t>::reverse_iterator i = out.rbegin(), j = out.rend();
            j--;
            for(; i != j; i++){
                *i >>= shift;
                i++;
                uint8_t temp = *i << (8 - shift);
                i--;
                *i += temp;
            }
            *j >>= shift;
        }
        return integer(out);
    }

继续做什么:

integer(1234567) / integer(6)

inside division algorithm (long division):

numerator       largest multiple of denomiator < numeator

12d687          0c0000
06d687          060000
d687            c000
1687            0c00
0a87            0600
0487            0300
0187            0c        <-- where did this come from??
017b            0180

是显示的某个运算符或其他运算符中的错误?

继承我的整个代码:http://ideone.com/ncq9S

1 个答案:

答案 0 :(得分:1)

template <typename T>

这真的需要参数化吗?似乎任何班次数量都可以存储在size_t中,并且在开始剩余的流程之前,隐式或明确地转换为size_t是一个好主意。

integer operator<<(T shift){

通常,二进制operator函数最好实现为非成员friend。例如,生成this指针时考虑的转换次数少于通用操作数。我写了friend integer operator<< ( integer lhs, size_t shift )

    std::list <uint8_t> out = value;

如果您使用friend和按值传递,则会隐式生成此副本。如果你真的只修改一个对象,编译器也可以更容易地消除它,例如q = q << 3

    for(unsigned int i = 0; i < (shift >> 3); i++)// get rid of bytes if shift > 8

在循环条件下要小心。您正在将运算符应用于高级类型,这可能会导致昂贵的计算(如果Tinteger,则甚至会无限递归!

    shift &= 7;                                   // shift by less than a byte

此时,如果shift == 0完成了。最好在此处插入条件return。此外,现在范围确实受限,因此请指定比T更窄的类型。

    out.push_front(0);                            // extra byte for overflow

仅当字节非零时才需要这样做。可能最好特殊情况下的第一个操作,并使push_front有条件,而不是特殊套管最后一个。

......嗯,看起来operator>>正在被更多地运用......跳到那个......

    for(; i != j; i++){
        i++;
        uint8_t temp = *i << (8 - shift);
        i--;
        *i += temp;
    }
    *j >>= shift;

显然,循环中缺少>>运算符。试试*i = *i >> shift + temp。此外,我没有看到列表如何缩短。这是在integer::integer( list<…> )吗?

完成的

但是,我无法真正看到在发布的输出中产生行为的原因。前导零可能是push_front中无条件operator<<的结果,但我期望的模式是c63,{{ 1}},18,....您似乎没有重复任何序列,而是随机跳转。

也许分区代码或类构造函数可以提供线索。